[carnelian] add ability for apps to publish additional services

Testing: manual
Change-Id: I08c8a5ecf8dd1fd9d10e4e36f43fbf222b457e4d
diff --git a/public/rust/carnelian/BUILD.gn b/public/rust/carnelian/BUILD.gn
index 4b57126..1ff6cc9 100644
--- a/public/rust/carnelian/BUILD.gn
+++ b/public/rust/carnelian/BUILD.gn
@@ -11,6 +11,7 @@
   version = "0.1.0"
   edition = "2018"
   deps = [
+    "//garnet/examples/fidl/services:echo2-rustc",
     "//garnet/public/fidl/fuchsia.fonts:fuchsia.fonts-rustc",
     "//garnet/public/fidl/fuchsia.images:fuchsia.images-rustc",
     "//garnet/public/fidl/fuchsia.math:fuchsia.math-rustc",
@@ -99,6 +100,7 @@
   edition = "2018"
   source_root = "examples/echo.rs"
   deps = [
+    "//garnet/examples/fidl/services:echo2-rustc",
     "//garnet/public/fidl/fuchsia.math:fuchsia.math-rustc",
     "//garnet/public/fidl/fuchsia.ui.gfx:fuchsia.ui.gfx-rustc",
     "//garnet/public/fidl/fuchsia.ui.scenic:fuchsia.ui.scenic-rustc",
@@ -182,5 +184,3 @@
     },
   ]
 }
-
-
diff --git a/public/rust/carnelian/examples/echo.rs b/public/rust/carnelian/examples/echo.rs
index 0f9dd09..56e34f1 100644
--- a/public/rust/carnelian/examples/echo.rs
+++ b/public/rust/carnelian/examples/echo.rs
@@ -2,11 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#![feature(async_await, await_macro, futures_api)]
+
 use carnelian::{App, AppAssistant, ViewAssistant, ViewAssistantContext, ViewAssistantPtr};
-use failure::{bail, Error};
+use failure::{Error, ResultExt};
+use fidl::endpoints::{RequestStream, ServiceMarker};
+use fidl_fidl_examples_echo::{EchoMarker, EchoRequest, EchoRequestStream};
 use fidl_fuchsia_ui_gfx::{self as gfx, ColorRgba};
 use fuchsia_async as fasync;
 use fuchsia_scenic::{Material, Rectangle, SessionPtr, ShapeNode};
+use futures::prelude::*;
 use parking_lot::Mutex;
 use std::{any::Any, cell::RefCell};
 
@@ -24,13 +29,30 @@
     }
 
     fn get_published_services_list(&self) -> Vec<&'static str> {
-        Vec::new()
+        vec![EchoMarker::NAME]
     }
 
     fn handle_service_request(
-        &mut self, _service_name: &str, _channel: fasync::Channel,
+        &mut self, service_name: &str, channel: fasync::Channel,
     ) -> Result<(), Error> {
-        bail!("handle_service_request not implemented");
+        if service_name == EchoMarker::NAME {
+            fasync::spawn(
+                async move {
+                    let mut stream = EchoRequestStream::from_channel(channel);
+                    while let Some(EchoRequest::EchoString { value, responder }) =
+                        await!(stream.try_next()).context("error running echo server")?
+                    {
+                        // TODO: Also display this in the view
+                        responder
+                            .send(value.as_ref().map(|s| &**s))
+                            .context("error sending response")?;
+                    }
+                    Ok(())
+                }
+                    .unwrap_or_else(|e: failure::Error| eprintln!("{:?}", e)),
+            );
+        }
+        Ok(())
     }
 }
 
@@ -73,7 +95,7 @@
     }
 
     fn handle_message(&mut self, _message: &Any) {
-        // If spinning square had any custom messages they
+        // If Echo had any custom messages they
         // would be handled here.
     }
 }