use super::*;
#[derive(Debug)]
pub enum CoapRequest {}
impl CoapRequest {
#[inline(always)]
pub fn get<IC>() -> SendGet<IC> {
Default::default()
}
#[inline(always)]
pub fn observe<IC>() -> SendObserve<IC> {
Default::default()
}
#[inline(always)]
pub fn post<IC>() -> SendPost<IC> {
Default::default()
}
#[inline(always)]
pub fn put<IC>() -> SendPut<IC> {
Default::default()
}
#[inline(always)]
pub fn delete<IC>() -> SendDelete<IC> {
Default::default()
}
#[inline(always)]
pub fn method<IC>(msg_code: MsgCode) -> CoapRequestMethod<IC> {
debug_assert!(msg_code.is_method(), "{:?} is not a method", msg_code);
CoapRequestMethod {
msg_code,
phantom: PhantomData,
}
}
}
macro_rules! send_desc_def_method {
($(#[$tags:meta])* $name:ident, $code:expr, $handler:expr) => {
$(#[$tags])*
#[derive(Debug)]
pub struct $ name < IC > (PhantomData < IC > );
send_desc_def_method!(@rest ($name,$code,$handler));
};
($name:ident, $code:expr, $handler:expr) => {
pub struct $ name < IC > (PhantomData < IC > );
send_desc_def_method!(@rest ($name,$code,$handler));
};
(@rest ($name:ident, $code:expr, $handler:expr)) => {
impl<IC> SendDescUnicast for $name<IC> {}
impl<IC> Default for $name<IC> {
#[inline(always)]
fn default() -> Self {
Self(PhantomData)
}
}
impl<IC> $name<IC> {
#[inline(always)]
pub fn nonconfirmable(self) -> Nonconfirmable<$name<IC>> {
Nonconfirmable(self)
}
#[inline(always)]
pub fn multicast(self) -> Multicast<$name<IC>> {
Multicast(self)
}
}
impl<IC: InboundContext> SendDesc<IC, ()> for $name<IC> {
fn write_options(
&self,
_msg: &mut dyn OptionInsert,
_socket_addr: &IC::SocketAddr,
_start: Bound<OptionNumber>,
_end: Bound<OptionNumber>,
) -> Result<(), Error> {
Ok(())
}
fn write_payload(
&self,
msg: &mut dyn MessageWrite,
_socket_addr: &IC::SocketAddr,
) -> Result<(), Error> {
msg.set_msg_code($code);
Ok(())
}
fn handler(
&mut self,
context: Result<&IC, Error>,
) -> Result<ResponseStatus<()>, Error> {
let context = context?;
if context.is_dupe() {
return Ok(ResponseStatus::Continue);
}
let code = context.message().msg_code();
($handler)(code)
}
}
};
}
send_desc_def_method!(
SendGet,
MsgCode::MethodGet,
|code| {
match code {
MsgCode::SuccessContent | MsgCode::SuccessValid => Ok(ResponseStatus::Done(())),
MsgCode::ClientErrorNotFound => Err(Error::ResourceNotFound),
MsgCode::ClientErrorForbidden => Err(Error::Forbidden),
MsgCode::ClientErrorUnauthorized => Err(Error::Unauthorized),
code if code.is_client_error() => Err(Error::ClientRequestError),
_ => Err(Error::ServerError),
}
}
);
send_desc_def_method!(
SendPut,
MsgCode::MethodPut,
|code| {
match code {
MsgCode::SuccessCreated | MsgCode::SuccessChanged | MsgCode::SuccessValid => {
Ok(ResponseStatus::Done(()))
}
MsgCode::ClientErrorNotFound => Err(Error::ResourceNotFound),
MsgCode::ClientErrorForbidden => Err(Error::Forbidden),
MsgCode::ClientErrorUnauthorized => Err(Error::Unauthorized),
code if code.is_client_error() => Err(Error::ClientRequestError),
_ => Err(Error::ServerError),
}
}
);
send_desc_def_method!(
SendPost,
MsgCode::MethodPost,
|code| {
match code {
code if code.is_success() => Ok(ResponseStatus::Done(())),
MsgCode::ClientErrorNotFound => Err(Error::ResourceNotFound),
MsgCode::ClientErrorForbidden => Err(Error::Forbidden),
MsgCode::ClientErrorUnauthorized => Err(Error::Unauthorized),
code if code.is_client_error() => Err(Error::ClientRequestError),
_ => Err(Error::ServerError),
}
}
);
send_desc_def_method!(
SendDelete,
MsgCode::MethodDelete,
|code| {
match code {
MsgCode::SuccessDeleted => Ok(ResponseStatus::Done(())),
MsgCode::ClientErrorNotFound => Err(Error::ResourceNotFound),
MsgCode::ClientErrorForbidden => Err(Error::Forbidden),
MsgCode::ClientErrorUnauthorized => Err(Error::Unauthorized),
code if code.is_client_error() => Err(Error::ClientRequestError),
_ => Err(Error::ServerError),
}
}
);
#[derive(Debug)]
pub struct CoapRequestMethod<IC> {
msg_code: MsgCode,
phantom: PhantomData<IC>,
}
impl<IC> SendDescUnicast for CoapRequestMethod<IC> {}
impl<IC> CoapRequestMethod<IC> {
#[inline(always)]
pub fn nonconfirmable(self) -> Nonconfirmable<CoapRequestMethod<IC>> {
Nonconfirmable(self)
}
#[inline(always)]
pub fn multicast(self) -> Multicast<CoapRequestMethod<IC>> {
Multicast(self)
}
}
impl<IC> SendDesc<IC, ()> for CoapRequestMethod<IC>
where
IC: InboundContext,
{
fn write_options(
&self,
_msg: &mut dyn OptionInsert,
_socket_addr: &IC::SocketAddr,
_start: Bound<OptionNumber>,
_end: Bound<OptionNumber>,
) -> Result<(), Error> {
Ok(())
}
fn write_payload(
&self,
msg: &mut dyn MessageWrite,
_socket_addr: &IC::SocketAddr,
) -> Result<(), Error> {
msg.set_msg_code(self.msg_code);
Ok(())
}
fn handler(&mut self, context: Result<&IC, Error>) -> Result<ResponseStatus<()>, Error> {
let context = context?;
if context.is_dupe() {
return Ok(ResponseStatus::Continue);
}
let code = context.message().msg_code();
match code {
code if code.is_success() => Ok(ResponseStatus::Done(())),
MsgCode::ClientErrorNotFound => Err(Error::ResourceNotFound),
MsgCode::ClientErrorForbidden => Err(Error::Forbidden),
MsgCode::ClientErrorUnauthorized => Err(Error::Unauthorized),
code if code.is_client_error() => Err(Error::ClientRequestError),
_ => Err(Error::ServerError),
}
}
}