blob: eab2b615c204af0e504f2840830716063af9555d [file] [log] [blame]
{{/*
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
*/}}
{{- define "DriverProtocolDeclaration" }}
{{- $protocol := . }}
{{- if eq $protocol.OverTransport "Driver" }}
#[cfg(feature = "driver")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct {{ $protocol.Marker }};
#[cfg(feature = "driver")]
impl fidl_driver::endpoints::DriverProtocolMarker for {{ $protocol.Marker }} {
const DEBUG_NAME: &'static str = "{{ $protocol.DebugName }}";
}
{{- range $method := $protocol.Methods }}
{{- if and $method.HasError (not $method.IsComposed) }}
pub type {{ $method.Response.TupleType }} = {{ $method.Response.TupleTypeAliasRhs }};
{{- end }}
{{- end }}
{{ "" }}
{{- range .DocComments }}
///{{ . }}
{{- end }}
{{ "" }}
#[cfg(feature = "driver")]
#[derive(Debug)]
pub enum {{ $protocol.Request }} {
{{- range $method := $protocol.Methods }}
{{- if $method.HasRequest }}
{{- range .DocComments }}
///{{ . }}
{{- end }}
{{ $method.CamelName }} {
{{- range $method.Request.Parameters }}
{{ .Name }}: {{ .OwnedType }},
{{- end }}
{{- if $method.HasResponse }}
responder: {{ $method.Responder }},
{{- end }}
},
{{- end }}
{{- end }}
{{- if $protocol.OneWayUnknownInteractions }}
/// An interaction was received which does not match any known method.
#[non_exhaustive]
_UnknownMethod {
/// Ordinal of the method that was called.
ordinal: u64,
{{- if $protocol.TwoWayUnknownInteractions }}
method_type: fidl::MethodType,
{{- end }}
},
{{- end }}
}
#[cfg(feature = "driver")]
impl {{ $protocol.Request }} {
{{- range $method := $protocol.Methods }}
{{- if $method.HasRequest }}
{{ "" }}
#[allow(irrefutable_let_patterns)]
pub fn into_{{ $method.Name }}(self) -> Option<(
{{- range $method.Request.Parameters }}
{{ .OwnedType }},
{{- end }}
{{- if $method.HasResponse }}
{{ $method.Responder }}
{{- end }}
)> {
if let {{ $protocol.Request }}::{{ $method.CamelName }} {
{{- range $method.Request.Parameters }}
{{ .Name }},
{{- end }}
{{- if $method.HasResponse }}
responder,
{{- end }}
} = self {
Some((
{{- range $method.Request.Parameters }}
{{- .Name }},
{{- end }}
{{- if $method.HasResponse }}
responder
{{- end -}}
))
} else {
None
}
}
{{- end }}
{{- end }}
{{- range $method := $protocol.Methods }}
{{- if $method.HasRequest }}
{{ "" }}
pub fn new_{{ $method.Name }}(self,
{{- range $method.Request.Parameters }}
{{ .Name }}: {{ .OwnedType }},
{{- end }}
{{- if $method.HasResponse }}
tx_id: u32,
{{- end }}
) -> Self {
Self::{{ $method.CamelName }} {
{{- range $method.Request.Parameters }}
{{ .Name }},
{{- end }}
{{- if $method.HasResponse }}
responder: {{ $method.Responder }} { tx_id },
{{- end }}
}
}
{{- end }}
{{- end }}
{{- range $method := $protocol.Methods }}
{{- if $method.HasRequest }}
{{ "" }}
pub fn r#{{ $method.Name }}_as_message(
arena: fdf::Arena,
{{- range $method.Request.Parameters }}
mut {{ .Name }}: {{ .Type }},
{{- end }}
{{- if $method.HasResponse }}
tx_id: u32,
{{- end }}
) -> Result<fdf::Message<[u8]>, fidl::Error> {
{{- if not $method.HasResponse }}
let tx_id = 0;
{{- end }}
let ordinal = {{ .Ordinal | printf "%#x" }};
let dynamic_flags = {{ .DynamicFlags }};
let body = {{ .Request.EncodeExpr }};
let msg =
fidl::encoding::TransactionMessage { header: fidl::encoding::TransactionHeader::new(tx_id, ordinal, dynamic_flags), body };
fidl::encoding::with_tls_encoded::<fidl::encoding::TransactionMessageType<{{ .Request.FidlType "fidl::encoding::DefaultFuchsiaResourceDialect" }}>, fidl::encoding::DefaultFuchsiaResourceDialect, fdf::Message<[u8]>>(msg, |bytes, mut handles| {
let handles = arena.insert_from_iter(std::mem::take(handles).into_iter().map(fidl_driver::encoding::mixed_from_handle_disposition));
Ok(fdf::Message::new(&arena, Some(arena.insert_slice(bytes)), Some(handles)))
})
}
{{- end }}
{{- end }}
#[allow(irrefutable_let_patterns)]
pub fn read_from(
bytes: &[u8],
_handles: &mut [zx::HandleInfo]
) -> Result<Self, fidl::Error> {
let (header, _body_bytes) = fidl::encoding::decode_transaction_header(bytes)?;
match header.ordinal {
{{- range $method := $protocol.Methods }}
{{- if $method.HasRequest }}
{{ .Ordinal | printf "%#x" }} => {
header.validate_request_tx_id(
{{- if $method.HasResponse -}}
fidl::MethodType::TwoWay
{{- else -}}
fidl::MethodType::OneWay
{{- end -}}
)?;
let mut req = fidl::new_empty!({{ $method.Request.FidlType "fidl::encoding::DefaultFuchsiaResourceDialect" }}, fidl::encoding::DefaultFuchsiaResourceDialect);
fidl::encoding::Decoder::<fidl::encoding::DefaultFuchsiaResourceDialect>::decode_into::<{{ $method.Request.FidlType "fidl::encoding::DefaultFuchsiaResourceDialect" }}>(&header, _body_bytes, _handles, &mut req)?;
Ok({{ $protocol.Request }}::{{ $method.CamelName }} {
{{- call $method.Request.ConvertToFields "req" }}
{{- if $method.HasResponse }}
responder: {{ $method.Responder }} {
tx_id: header.tx_id,
},
{{- else }}
{{- end }}
})
}
{{- end }}
{{- end }}
{{- if $protocol.OneWayUnknownInteractions }}
_ if header.tx_id == 0 && header.dynamic_flags().contains(fidl::encoding::DynamicFlags::FLEXIBLE) => {
Ok({{ $protocol.Request }}::_UnknownMethod {
ordinal: header.ordinal,
{{- if $protocol.TwoWayUnknownInteractions }}
method_type: fidl::MethodType::OneWay,
{{- end }}
})
}
{{- if $protocol.TwoWayUnknownInteractions }}
_ if header.dynamic_flags().contains(fidl::encoding::DynamicFlags::FLEXIBLE) => {
Ok({{ $protocol.Request }}::_UnknownMethod {
ordinal: header.ordinal,
method_type: fidl::MethodType::TwoWay,
})
}
{{- end }}
{{- end }}
_ => Err(fidl::Error::UnknownOrdinal {
ordinal: header.ordinal,
protocol_name: <{{ $protocol.Marker }} as fidl_driver::endpoints::DriverProtocolMarker>::DEBUG_NAME
}),
}
}
pub fn read_from_message(mut message: fdf::Message<[u8]>) -> Result<(fdf::Arena, Self), fidl::Error> {
let (arena, Some(body), Some(handles)) = message.take_arena_boxes() else {
return Err(fidl::Error::Invalid)
};
let mut handles = arena.try_insert_from_iter(handles.into_iter().map(|handle| {
unsafe { fidl_driver::encoding::mixed_into_handle_info(handle) }
}));
let res = match handles {
Ok(ref mut handles) => Self::read_from(&*body, handles)?,
Err(_) => return Err(fidl::Error::Invalid),
};
std::mem::drop((body, handles));
Ok((message.take_arena(), res))
}
/// Name of the method defined in FIDL
pub fn method_name(&self) -> &'static str {
match *self {
{{- range $method := $protocol.Methods }}
{{- if $method.HasRequest }}
{{ $protocol.Request }}::{{ $method.CamelName }}{..} => "{{ $method.Name }}",
{{- end }}
{{- end }}
{{- if $protocol.TwoWayUnknownInteractions }}
{{ $protocol.Request }}::_UnknownMethod {
method_type: fidl::MethodType::OneWay, ..
} => "unknown one-way method",
{{ $protocol.Request }}::_UnknownMethod {
method_type: fidl::MethodType::TwoWay, ..
} => "unknown two-way method",
{{- else if $protocol.OneWayUnknownInteractions }}
{{ $protocol.Request }}::_UnknownMethod {..} => "unknown one-way method",
{{- end }}
}
}
}
/// Like [`{{ $protocol.Request }}::read_from_message`] except it drops the [`Arena`].
#[cfg(feature = "driver")]
impl std::convert::TryFrom<fdf::Message<[u8]>> for {{ $protocol.Request }} {
type Error = fidl::Error;
fn try_from(msg: fdf::Message<[u8]>) -> Result<{{ $protocol.Request }}, fidl::Error> {
Ok({{ $protocol.Request }}::read_from_message(msg)?.1)
}
}
{{- range $method := $protocol.Methods }}
{{ "" }}
{{- if and $method.HasRequest $method.HasResponse }}
#[must_use = "FIDL methods require a response to be sent"]
#[cfg(feature = "driver")]
#[derive(Debug)]
pub struct {{ $method.Responder }} {
tx_id: u32,
}
#[cfg(feature = "driver")]
impl {{ $method.Responder }} {
pub fn send_response(&self, server_handle: &fdf::Channel<[u8]>,
{{- range $method.Response.Parameters }}
mut {{ .Name }}: {{ .Type }},
{{- end }}
) -> Result<(), fidl::Error> {
let msg = fidl::encoding::TransactionMessage {
header: fidl::encoding::TransactionHeader::new(self.tx_id, {{ $method.Ordinal | printf "%#x" }}, {{ $method.DynamicFlags }}),
body: {{ $method.Response.EncodeExpr }},
};
fidl::encoding::with_tls_encoded::<fidl::encoding::TransactionMessageType<{{ $method.Response.FidlType "fidl::encoding::DefaultFuchsiaResourceDialect" }}>, fidl::encoding::DefaultFuchsiaResourceDialect, ()>(msg, |body, _handles| {
server_handle.write_with_data(fdf::Arena::new(), |arena| arena.insert_slice(&body)).unwrap();
Ok(())
})
}
}
{{- end }}
{{- end }}
{{- end }}
{{- end }}