///|
pub(all) enum AcceptStatus {
Success(Array[Byte])
ProgramUnavailable
ProgramMismatch(UInt, UInt)
ProcedureUnavailable
GarbageArguments
SystemError
}
///|
pub(all) enum RejectStatus {
RpcMismatch(UInt, UInt)
AuthError(UInt)
}
///|
pub(all) enum ReplyBody {
Accepted(OpaqueAuth, AcceptStatus)
Rejected(RejectStatus)
}
///|
pub(all) struct RpcReply {
xid : UInt
body : ReplyBody
}
///|
fn Writer::write_versions(
self : Writer,
low : UInt,
high : UInt,
) -> Unit raise XdrError {
if low > high {
raise Invalid(self.length(), "reversed RPC version range")
}
self.write_uint(low)
self.write_uint(high)
}
///|
fn Reader::read_versions(self : Reader) -> (UInt, UInt) raise XdrError {
let low = self.read_uint()
let high = self.read_uint()
if low > high {
raise Invalid(self.position() - 8, "reversed RPC version range")
}
(low, high)
}
///|
pub fn encode_reply(
reply : RpcReply,
limits? : Limits = Limits::default(),
) -> Array[Byte] raise XdrError {
let w = Writer::new(limits~)
w.write_uint(reply.xid)
w.write_uint(1U)
match reply.body {
Accepted(verifier, status) => {
w.write_uint(0U)
w.write_auth(verifier)
match status {
Success(result) => {
if result.length() % 4 != 0 {
raise Invalid(w.length(), "RPC result must be XDR aligned")
}
w.write_uint(0U)
w.write_raw(result)
}
ProgramUnavailable => w.write_uint(1U)
ProgramMismatch(low, high) => {
w.write_uint(2U)
w.write_versions(low, high)
}
ProcedureUnavailable => w.write_uint(3U)
GarbageArguments => w.write_uint(4U)
SystemError => w.write_uint(5U)
}
}
Rejected(reason) => {
w.write_uint(1U)
match reason {
RpcMismatch(low, high) => {
w.write_uint(0U)
w.write_versions(low, high)
}
AuthError(status) => {
w.write_uint(1U)
w.write_uint(status)
}
}
}
}
w.bytes()
}
///|
pub fn decode_reply(
bytes : Array[Byte],
limits? : Limits = Limits::default(),
) -> RpcReply raise XdrError {
let r = Reader::new(bytes, limits~)
let xid = r.read_uint()
if r.read_uint() != 1U {
raise Invalid(4, "expected RPC REPLY")
}
let body = match r.read_uint() {
0U => {
let verifier = r.read_auth()
let status = match r.read_uint() {
0U => {
if r.remaining() % 4 != 0 {
raise Invalid(r.position(), "unaligned RPC result")
}
Success(r.read_raw(r.remaining()))
}
1U => ProgramUnavailable
2U => {
let (low, high) = r.read_versions()
ProgramMismatch(low, high)
}
3U => ProcedureUnavailable
4U => GarbageArguments
5U => SystemError
_ => raise Invalid(r.position() - 4, "unknown RPC accept status")
}
Accepted(verifier, status)
}
1U => {
let reason = match r.read_uint() {
0U => {
let (low, high) = r.read_versions()
RpcMismatch(low, high)
}
1U => AuthError(r.read_uint())
_ => raise Invalid(r.position() - 4, "unknown RPC reject status")
}
Rejected(reason)
}
_ => raise Invalid(8, "unknown RPC reply status")
}
r.finish()
{ xid, body, }
}