Skip to content

Commit

Permalink
Merge pull request #9 from Riey/tinput
Browse files Browse the repository at this point in the history
Implement TINPUT/ONEINPUT
  • Loading branch information
Riey authored Oct 6, 2022
2 parents 9361ecf + c652f5c commit a040378
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 111 deletions.
23 changes: 21 additions & 2 deletions HTTP.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,26 @@ struct Ret {
lines: [{parts: [ConsoleLinePart]}]
}

enum InputRequest {
struct InputRequest {
generation: u32,
ty: InputRequestType,
timeout: Option<Timeout>,
is_one: bool,
}

enum InputRequestType {
Anykey,
EnterKey,
Int,
Str,
}

struct Timeout {
timeout: u32,
show_timer: bool,
timeout_msg: String,
}

enum ConsoleLinePart {
Text(String, TextStyle),
Line(String, TextStyle),
Expand Down Expand Up @@ -56,4 +69,10 @@ Int일시엔 꼭 숫자 문자열로 전송 Str이면 그냥 그대로 전송

웹소켓 연결 가능

연결시 UI가 업데이트 될때마다 아무 메세지를 전송함
연결시 이밴트 발생시 메세지로 전송해줌

## 이밴트 목록

* REDRAW(1)

* TIMEOUT(2)
17 changes: 17 additions & 0 deletions erars-ast/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ pub enum Value {
String(String),
}

impl Default for Value {
fn default() -> Self {
Value::Int(0)
}
}

impl Value {
pub const ZERO: Value = Value::Int(0);
pub const ONE: Value = Value::Int(1);
Expand Down Expand Up @@ -69,6 +75,17 @@ impl TryFrom<Value> for usize {
}
}

impl TryFrom<Value> for u32 {
type Error = Error;

fn try_from(value: Value) -> Result<Self, Self::Error> {
match value {
Value::Int(i) => Ok(i.try_into()?),
_ => bail!("Value is not int"),
}
}
}

impl TryFrom<Value> for i64 {
type Error = Error;

Expand Down
101 changes: 92 additions & 9 deletions src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ use regex::Regex;
use serde::{Deserialize, Serialize};
use smol_str::SmolStr;
use std::collections::VecDeque;
use std::sync::atomic::AtomicU32;
use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
use std::sync::Arc;
use std::time::Duration;
use tokio::time::Instant;

#[cfg(feature = "stdio-backend")]
mod stdio_backend;
Expand Down Expand Up @@ -130,9 +132,10 @@ impl ConsoleLine {
}

/// Used by ui backend
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Eq)]
struct VirtualConsole {
pub current_req: Option<InputRequest>,
timeout: Option<(Instant, u32, Value)>,
lines: Vec<ConsoleLine>,
style: TextStyle,
bg_color: Color,
Expand All @@ -143,6 +146,7 @@ impl VirtualConsole {
fn new() -> Self {
Self {
current_req: None,
timeout: None,
lines: Vec::new(),
style: TextStyle {
color: Color([255, 255, 255]),
Expand All @@ -164,8 +168,12 @@ impl VirtualConsole {
}
match com {
ConsoleMessage::Input(req) => {
if self.current_req.is_some() {
log::warn!("Input overwrited");
if let Some(timeout) = req.timeout.as_ref() {
self.timeout = Some((
Instant::now() + Duration::from_millis(timeout.timeout as _),
req.generation,
timeout.default_value.clone(),
));
}
self.current_req = Some(req);
}
Expand Down Expand Up @@ -250,13 +258,56 @@ bitflags::bitflags! {
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum InputRequest {
Anykey,
pub enum InputRequestType {
AnyKey,
EnterKey,
Int,
Str,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
/// input timeout
pub struct Timeout {
pub timeout: u32,
#[serde(skip)]
pub default_value: Value,
pub timeout_msg: Option<String>,
pub show_timer: bool,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct InputRequest {
/// InputRequest generation
pub generation: u32,
/// type of request
pub ty: InputRequestType,
/// whether is ONEINPUT or not
pub is_one: bool,
#[serde(skip_serializing_if = "Option::is_none")]
/// TINPUT
pub timeout: Option<Timeout>,
}

impl InputRequest {
pub fn normal(gen: u32, ty: InputRequestType) -> Self {
Self {
generation: gen,
ty,
is_one: false,
timeout: None,
}
}

pub fn oneinput(gen: u32, ty: InputRequestType) -> Self {
Self {
generation: gen,
ty,
is_one: true,
timeout: None,
}
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ConsoleResult {
Quit,
Expand Down Expand Up @@ -318,7 +369,12 @@ impl ConsoleSender {
Value::Int(i) => break Some(i),
}
} else {
self.chan.send_msg(ConsoleMessage::Input(InputRequest::Int));
self.chan.send_msg(ConsoleMessage::Input(InputRequest {
generation: self.chan.input_gen(),
ty: InputRequestType::Int,
is_one: false,
timeout: None,
}));
let ret = self.chan.recv_ret();

match ret {
Expand All @@ -330,10 +386,18 @@ impl ConsoleSender {
}
}

pub fn input_gen(&self) -> u32 {
self.chan.input_gen()
}

pub fn input(&mut self, req: InputRequest) -> ConsoleResult {
self.request_redraw();

if matches!(req, InputRequest::Anykey | InputRequest::EnterKey) && !self.inputs.is_empty() {
if matches!(
req.ty,
InputRequestType::AnyKey | InputRequestType::EnterKey
) && !self.inputs.is_empty()
{
ConsoleResult::Value(0.into())
} else if let Some(i) = self.inputs.pop_front() {
ConsoleResult::Value(i)
Expand Down Expand Up @@ -476,6 +540,7 @@ pub struct ConsoleChannel {
exit_fn: Mutex<Option<Box<dyn Fn() + Send + Sync>>>,
delay_redraw: AtomicBool,
delay_exit: AtomicBool,
input_generation: AtomicU32,
console: (Sender<ConsoleMessage>, Receiver<ConsoleMessage>),
ret: (Sender<ConsoleResult>, Receiver<ConsoleResult>),
}
Expand All @@ -487,11 +552,16 @@ impl ConsoleChannel {
exit_fn: Mutex::new(None),
delay_redraw: AtomicBool::new(false),
delay_exit: AtomicBool::new(false),
input_generation: AtomicU32::new(0),
console: bounded(256),
ret: bounded(8),
}
}

pub fn input_gen(&self) -> u32 {
self.input_generation.load(SeqCst)
}

pub fn set_redraw_fn(&self, f: impl Fn() + Send + Sync + 'static) {
let mut redraw_fn = self.redraw_fn.lock();

Expand Down Expand Up @@ -542,8 +612,21 @@ impl ConsoleChannel {
self.console.1.recv_timeout(Duration::from_millis(50)).ok()
}

pub fn send_ret(&self, ret: ConsoleResult) {
self.ret.0.send(ret).unwrap()
pub fn send_quit(&self) {
self.ret.0.send(ConsoleResult::Quit).unwrap()
}

pub fn send_input(&self, input: Value, gen: u32) -> bool {
if self
.input_generation
.compare_exchange(gen, gen.wrapping_add(1), SeqCst, SeqCst)
.is_ok()
{
self.ret.0.send(ConsoleResult::Value(input)).unwrap();
true
} else {
false
}
}

pub fn recv_ret(&self) -> ConsoleResult {
Expand Down
Loading

0 comments on commit a040378

Please sign in to comment.