///|
/// An enum's values are numbered by its tags, or in order from 0, and named
/// with the enum's name in front: `MOOD_CALM`. A number it does not know reads
/// as its first value.
#rpc.enum
pub enum Mood {
Calm = 0
Glad = 1
Grumpy = 5
}
///|
/// Fields are numbered in declaration order; `number=` sets one, and the
/// count carries on from there. `T?` is proto3 `optional`, `Map[K, V]` is a
/// `map`.
#rpc.message
pub struct HelloRequest {
name : String
#rpc.field(number="4")
tags : Array[String]
nickname : String?
mood : Mood
extras : Map[String, Int64]
}
///|
/// A dotted name nests the message in another: `.greet.HelloReply.Badge`.
#rpc.message(name="HelloReply.Badge")
pub struct Badge {
label : String
}
///|
#rpc.message
pub struct HelloReply {
message : String
calls : Int64
scores : Array[Int32]
ratio : Double
badges : Array[Badge]
#rpc.skip
cached : Bool
}
///|
#rpc.message
pub struct Upto {
n : Int32
}
///|
#rpc.message
pub struct Number {
value : Int32
}
///|
/// A service is a struct, so it carries state; its `#rpc.method`s are the RPCs,
/// named in PascalCase. `name` is the full name, its package before the last dot.
#rpc.service(name="greet.Greeter")
pub struct Greeter {
greeting : String
}
///|
/// A `StatusError` answers with that status; a parameter of type `RpcContext`
/// receives the call's context.
#rpc.method
fn Greeter::say_hello(
self : Greeter,
ctx : @moonrpc.RpcContext,
req : HelloRequest,
) -> HelloReply raise {
if req.name == "" {
raise @wire.StatusError(InvalidArgument, "a name, please")
}
ctx.add_header(b"x-greeter", b"annotated")
let who = req.nickname.unwrap_or(req.name)
{
message: "\{self.greeting}, \{who}",
calls: req.extras.get("calls").unwrap_or(9000000000),
scores: req.tags.map(t => t.length()),
ratio: 0.5,
badges: if req.mood is Grumpy {
[{ label: "grumpy", }]
} else {
[]
},
cached: false,
}
}
///|
/// Returning an array streams the replies.
#rpc.method
fn Greeter::count_to(self : Greeter, req : Upto) -> Array[Number] {
ignore(self)
Array::makei(req.n, i => { value: i + 1, })
}
///|
/// Taking an array receives a client stream.
#rpc.method(name="Sum")
fn Greeter::add_up(self : Greeter, req : Array[Number]) -> Number {
ignore(self)
{ value: req.fold(init=0, (acc, x) => acc + x.value), }
}
///|
/// Taking and returning arrays is a bidirectional stream, answered once the
/// client half-closes.
#rpc.method
fn Greeter::echo(self : Greeter, req : Array[Number]) -> Array[Number] {
ignore(self)
req.rev()
}