mod get; mod set; use log; use std::io::{Read, Write}; use super::{ConfigError, Configuration}; use get::serialize; use set::LineParser; const MAX_LINE_LENGTH: usize = 256; pub fn handle(stream: &mut S, config: &C) { fn operation( stream: &mut S, config: &C, ) -> Result<(), ConfigError> { // read string up to maximum length (why is this not in std?) fn readline(reader: &mut R) -> Result { let mut m: [u8; 1] = [0u8]; let mut l: String = String::with_capacity(MAX_LINE_LENGTH); while let Ok(_) = reader.read_exact(&mut m) { let c = m[0] as char; if c == '\n' { log::trace!("UAPI, line: {}", l); return Ok(l); }; l.push(c); if l.len() > MAX_LINE_LENGTH { return Err(ConfigError::LineTooLong); } } return Err(ConfigError::IOError); } // split into (key, value) pair fn keypair<'a>(ln: &'a str) -> Result<(&'a str, &'a str), ConfigError> { let mut split = ln.splitn(2, "="); match (split.next(), split.next()) { (Some(key), Some(value)) => Ok((key, value)), _ => Err(ConfigError::LineTooLong), } }; // read operation line match readline(stream)?.as_str() { "get=1" => { log::debug!("UAPI, Get operation"); serialize(stream, config).map_err(|_| ConfigError::IOError) } "set=1" => { log::debug!("UAPI, Set operation"); let mut parser = LineParser::new(config); loop { let ln = readline(stream)?; if ln == "" { // end of transcript parser.parse_line("", "")?; // flush final peer break Ok(()); } else { let (k, v) = keypair(ln.as_str())?; parser.parse_line(k, v)?; }; } } _ => Err(ConfigError::InvalidOperation), } } // process operation let res = operation(stream, config); log::debug!("UAPI, Result of operation: {:?}", res); // return errno let _ = stream.write("errno=".as_ref()); let _ = stream.write( match res { Err(e) => e.errno().to_string(), Ok(()) => "0".to_owned(), } .as_ref(), ); let _ = stream.write("\n\n".as_ref()); }