From abb4dee09e2496c7123c45e134f60fd3fbf76835 Mon Sep 17 00:00:00 2001
From: Matt Johnston <matt@ucc.asn.au>
Date: Sat, 8 Apr 2023 14:14:01 +0800
Subject: [PATCH] Make menu BufOutput non-failing.

Some other RAM reductions
---
 embassy/demos/common/server.rs  | 19 ++++++++++++++-----
 embassy/demos/picow/src/main.rs |  2 +-
 embassy/src/server.rs           |  2 +-
 src/conn.rs                     |  2 ++
 src/namelist.rs                 |  5 ++++-
 5 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/embassy/demos/common/server.rs b/embassy/demos/common/server.rs
index b1f561b..c5912b1 100644
--- a/embassy/demos/common/server.rs
+++ b/embassy/demos/common/server.rs
@@ -185,7 +185,8 @@ pub trait Shell : Default {
 /// asynchronously to a channel.
 #[derive(Default)]
 pub struct BufOutput {
-    s: heapless::String<1024>,
+    /// Sufficient to hold output produced from a single keystroke input. Further output will be discarded
+    s: heapless::String<300>,
 }
 
 impl BufOutput {
@@ -205,12 +206,20 @@ impl BufOutput {
 
 impl core::fmt::Write for BufOutput {
     fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
-        for c in s.chars() {
-            if c == '\n' {
-                self.s.push('\r').map_err(|_| core::fmt::Error)?;
+        let mut inner = || {
+            for c in s.chars() {
+                if c == '\n' {
+                    self.s.push('\r').map_err(|_| core::fmt::Error)?;
+                }
+                self.s.push(c).map_err(|_| core::fmt::Error)?;
             }
-            self.s.push(c).map_err(|_| core::fmt::Error)?;
+            Ok::<_, core::fmt::Error>(())
+        };
+
+        if inner().is_err() {
+            trace!("Buffer full in BufOutput");
         }
+
         Ok(())
     }
 }
diff --git a/embassy/demos/picow/src/main.rs b/embassy/demos/picow/src/main.rs
index 7fb1bd3..39eb0e2 100644
--- a/embassy/demos/picow/src/main.rs
+++ b/embassy/demos/picow/src/main.rs
@@ -109,8 +109,8 @@ impl Shell for DemoShell {
                 let b = &mut b[..lr];
                 for c in b.iter() {
                     menu.input_byte(*c);
+                    menu.context.flush(&mut stdio).await?;
                 }
-                menu.context.flush(&mut stdio).await?;
             }
             Ok(())
         };
diff --git a/embassy/src/server.rs b/embassy/src/server.rs
index 2bdc685..7954c5d 100644
--- a/embassy/src/server.rs
+++ b/embassy/src/server.rs
@@ -3,7 +3,7 @@ use embassy_sync::blocking_mutex::raw::RawMutex;
 use embedded_io::asynch;
 
 use sunset::*;
-use sunset::behaviour::{UnusedCli, UnusedServ};
+use sunset::behaviour::UnusedCli;
 
 use crate::*;
 use embassy_sunset::EmbassySunset;
diff --git a/src/conn.rs b/src/conn.rs
index e42c82f..d203ed4 100644
--- a/src/conn.rs
+++ b/src/conn.rs
@@ -39,6 +39,8 @@ pub(crate) struct Conn<C: CliBehaviour, S: ServBehaviour> {
     parse_ctx: ParseContext,
 
     /// Remote version string. Kept for later kexinit rekeying
+    // TODO: could save space by hashing it into a KexHash and storing that instead.
+    // 256 bytes -> 112 bytes
     pub(crate) remote_version: ident::RemoteVersion,
 
     pub(crate) channels: Channels<C, S>,
diff --git a/src/namelist.rs b/src/namelist.rs
index 78b9a40..f871fac 100644
--- a/src/namelist.rs
+++ b/src/namelist.rs
@@ -18,7 +18,10 @@ use heapless::Vec;
 // - key types
 // - signature types
 // - auth types
-pub const MAX_LOCAL_NAMES: usize = 5;
+/// Max count of LocalNames entries
+///
+/// Current max is for kex, [curve25519, curve25519@libssh, ext-info, kexguess2]
+pub const MAX_LOCAL_NAMES: usize = 4;
 static EMPTY_LOCALNAMES: LocalNames = LocalNames::new();
 
 /// A comma separated string, can be decoded or encoded.
-- 
GitLab