char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
c7a9569
main
1use crate :: Result ; 2use serde_json:: Value ; 3use tokio:: io::{ AsyncBufRead , AsyncBufReadExt , AsyncReadExt , AsyncWrite , AsyncWriteExt }; 4 5# [ derive ( Debug , serde :: Deserialize , thiserror :: Error )] 6# [ error ( "{message}" )] 7pub ( crate ) struct RpcError { 8pub code : i64 , 9pub message : String , 10# [ serde ( default )] 11pub data : Option < Value >, 12} 13impl RpcError { 14pub fn invalid ( message : impl Into < String >) ->Self { 15Self { 16code : -32602 , 17message : message. into (), 18data : None , 19} 20} 21pub fn failed ( message : impl Into < String >) ->Self { 22Self { 23code : -32803 , 24message : message. into (), 25data : None , 26} 27} 28pub fn modified () ->Self { 29Self { 30code : -32801 , 31message : "Language-service item is stale; request it again" . into (), 32data : None , 33} 34} 35} 36 37const MAX_HEADER : usize =8192 ; 38const MAX_BODY : usize =64 * 1024 * 1024 ; 39 40pub async fn read ( reader : & mut ( impl AsyncBufRead +Unpin )) ->Result < Option < Value >> { 41let mut header =Vec :: new (); 42loop { 43let available = reader. fill_buf (). await ?; 44if available. is_empty () { 45return if header. is_empty () { 46Ok ( None ) 47} else { 48Err ( "Truncated RPC header" . into ()) 49}; 50} 51let count = available 52. iter () 53. position ( |b|* b ==b'\n' ) 54. map_or ( available. len (), |i| i +1 ); 55if header. len () + count >MAX_HEADER { 56return Err ( "RPC header exceeds limit" . into ()); 57} 58 header. extend_from_slice ( & available[ ..count]); 59 reader. consume ( count); 60if header. ends_with ( b"\r\n\r\n" ) { 61break ; 62} 63} 64let mut length =None ; 65for linein std:: str:: from_utf8 ( & header) ? 66. split ( "\r\n" ) 67. filter ( |s| !s. is_empty ()) 68{ 69let ( name, value) = line. split_once ( ':' ). ok_or ( "Invalid RPC header" ) ?; 70if name. eq_ignore_ascii_case ( "content-length" ) { 71if length. is_some () { 72return Err ( "Duplicate Content-Length" . into ()); 73} 74 length =Some ( value. trim (). parse ::< usize >() ?); 75} 76} 77let length = length. ok_or ( "Missing Content-Length" ) ?; 78if length >MAX_BODY { 79return Err ( "RPC body exceeds limit" . into ()); 80} 81let mut body =vec! [ 0 ; length]; 82 reader. read_exact ( & mut body). await ?; 83let message: Value = serde_json:: from_slice ( & body) ?; 84if !message. is_object () || message[ "jsonrpc" ] !="2.0" { 85return Err ( "Invalid JSON-RPC message" . into ()); 86} 87Ok ( Some ( message)) 88} 89 90pub async fn write ( writer : & mut ( impl AsyncWrite +Unpin ), mut message : Value ) ->Result <()> { 91 message[ "jsonrpc" ] =Value :: String ( "2.0" . into ()); 92let body = serde_json:: to_vec ( & message) ?; 93if body. len () >MAX_BODY { 94return Err ( "RPC body exceeds limit" . into ()); 95} 96 writer 97. write_all ( format! ( "Content-Length: {}\r\n\r\n" , body. len ()). as_bytes ()) 98. await ?; 99 writer. write_all ( & body). await ?; 100 writer. flush (). await ?; 101Ok (()) 102} 103 104# [ cfg ( test )] 105mod tests{ 106use super :: * ; 107use serde_json:: json; 108use tokio:: io:: BufReader ; 109# [ tokio :: test ] 110async fn utf8_and_multiple_frames () { 111let mut bytes =Vec :: new (); 112write ( & mut bytes, json! ({ "id" : 1 , "result" : "😀" })) 113. await 114. unwrap (); 115write ( & mut bytes, json! ({ "id" : 2 , "result" : "next" })) 116. await 117. unwrap (); 118let mut input =BufReader :: with_capacity ( 1 , bytes. as_slice ()); 119assert_eq! ( read ( & mut input). await . unwrap (). unwrap ()[ "result" ], "😀" ); 120assert_eq! ( read ( & mut input). await . unwrap (). unwrap ()[ "result" ], "next" ); 121assert! ( read ( & mut input). await . unwrap (). is_none ()); 122} 123# [ tokio :: test ] 124async fn malformed_and_bounded () { 125for bytesin [ 126b"Content-Length: 9\r\n\r\n{}" . as_slice (), 127b"Content-Length: 1\r\nContent-Length: 1\r\n\r\n0" , 128b"Content-Length: 999999999\r\n\r\n" , 129] { 130assert! ( read ( & mut BufReader :: new ( bytes)). await . is_err ()); 131} 132assert! ( 133read ( & mut BufReader :: new ( vec! [ b'x' ; MAX_HEADER +1 ]. as_slice ())) 134. await 135. is_err () 136); 137} 138}