#![allow(clippy::type_complexity)]
use crate::field::num::{F1, F2};
use crate::field::{FieldDecoder, FieldEncoder, Fields, MaybeDefault};
use crate::message::{MessageDecode, MessageDecoder, MessageEncode, MessageEncoder};
use crate::scalar::{Int32Decoder, Int32Encoder, Int64Decoder, Int64Encoder};
use bytecodec::{ByteCount, Decode, Encode, Eos, ErrorKind, Result, SizedEncode};
use std::time::Duration;
#[derive(Debug, Default)]
pub struct EmptyMessageDecoder(MessageDecoder<Fields<()>>);
impl EmptyMessageDecoder {
pub fn new() -> Self {
Self::default()
}
}
impl Decode for EmptyMessageDecoder {
type Item = ();
fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize> {
track!(self.0.decode(buf, eos))
}
fn finish_decoding(&mut self) -> Result<Self::Item> {
track!(self.0.finish_decoding())
}
fn requiring_bytes(&self) -> ByteCount {
self.0.requiring_bytes()
}
fn is_idle(&self) -> bool {
self.0.is_idle()
}
}
impl MessageDecode for EmptyMessageDecoder {}
#[derive(Debug, Default)]
pub struct EmptyMessageEncoder(MessageEncoder<Fields<()>>);
impl EmptyMessageEncoder {
pub fn new() -> Self {
Self::default()
}
}
impl Encode for EmptyMessageEncoder {
type Item = ();
fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result<usize> {
track!(self.0.encode(buf, eos))
}
fn start_encoding(&mut self, (): Self::Item) -> Result<()> {
track!(self.0.start_encoding(()))
}
fn requiring_bytes(&self) -> ByteCount {
self.0.requiring_bytes()
}
fn is_idle(&self) -> bool {
self.0.is_idle()
}
}
impl SizedEncode for EmptyMessageEncoder {
fn exact_requiring_bytes(&self) -> u64 {
self.0.exact_requiring_bytes()
}
}
impl MessageEncode for EmptyMessageEncoder {}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct DurationMessage {
seconds: i64,
nanos: i32,
}
impl DurationMessage {
pub const MIN_SECONDS: i64 = -315_576_000_000;
pub const MAX_SECONDS: i64 = 315_576_000_000;
pub const MIN_NANOS: i32 = -999_999_999;
pub const MAX_NANOS: i32 = 999_999_999;
pub fn new(seconds: i64, nanos: i32) -> Result<Self> {
track_assert!(Self::MIN_SECONDS <= seconds, ErrorKind::InvalidInput; seconds, nanos);
track_assert!(seconds <= Self::MAX_SECONDS, ErrorKind::InvalidInput; seconds, nanos);
track_assert!(Self::MIN_NANOS <= nanos, ErrorKind::InvalidInput; seconds, nanos);
track_assert!(nanos <= Self::MAX_NANOS, ErrorKind::InvalidInput; seconds, nanos);
Ok(DurationMessage { seconds, nanos })
}
pub fn from_duration(d: Duration) -> Result<Self> {
track!(Self::new(d.as_secs() as i64, d.subsec_nanos() as i32))
}
pub fn seconds(&self) -> i64 {
self.seconds
}
pub fn nanos(&self) -> i32 {
self.nanos
}
pub fn to_duration(&self) -> Option<Duration> {
if self.seconds >= 0 && self.nanos >= 0 {
Some(Duration::new(self.seconds as u64, self.nanos as u32))
} else {
None
}
}
}
#[derive(Debug, Default)]
pub struct DurationMessageDecoder {
inner: MessageDecoder<
Fields<(
MaybeDefault<FieldDecoder<F1, Int64Decoder>>,
MaybeDefault<FieldDecoder<F2, Int32Decoder>>,
)>,
>,
}
impl DurationMessageDecoder {
pub fn new() -> Self {
Self::default()
}
}
impl Decode for DurationMessageDecoder {
type Item = DurationMessage;
fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize> {
track!(self.inner.decode(buf, eos))
}
fn finish_decoding(&mut self) -> Result<Self::Item> {
let (seconds, nanos) = track!(self.inner.finish_decoding())?;
track!(DurationMessage::new(seconds, nanos))
}
fn requiring_bytes(&self) -> ByteCount {
self.inner.requiring_bytes()
}
fn is_idle(&self) -> bool {
self.inner.is_idle()
}
}
impl MessageDecode for DurationMessageDecoder {}
#[derive(Debug, Default)]
pub struct DurationMessageEncoder {
inner: MessageEncoder<
Fields<(
MaybeDefault<FieldEncoder<F1, Int64Encoder>>,
MaybeDefault<FieldEncoder<F2, Int32Encoder>>,
)>,
>,
}
impl DurationMessageEncoder {
pub fn new() -> Self {
Self::default()
}
}
impl Encode for DurationMessageEncoder {
type Item = DurationMessage;
fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result<usize> {
track!(self.inner.encode(buf, eos))
}
fn start_encoding(&mut self, item: Self::Item) -> Result<()> {
let item = (item.seconds, item.nanos);
track!(self.inner.start_encoding(item))
}
fn requiring_bytes(&self) -> ByteCount {
self.inner.requiring_bytes()
}
fn is_idle(&self) -> bool {
self.inner.is_idle()
}
}
impl SizedEncode for DurationMessageEncoder {
fn exact_requiring_bytes(&self) -> u64 {
self.inner.exact_requiring_bytes()
}
}
impl MessageEncode for DurationMessageEncoder {}
#[derive(Debug, Default)]
pub struct StdDurationDecoder(DurationMessageDecoder);
impl StdDurationDecoder {
pub fn new() -> Self {
Self::default()
}
}
impl Decode for StdDurationDecoder {
type Item = Duration;
fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize> {
track!(self.0.decode(buf, eos))
}
fn finish_decoding(&mut self) -> Result<Self::Item> {
let m = track!(self.0.finish_decoding())?;
let d = track_assert_some!(m.to_duration(), ErrorKind::InvalidInput; m);
Ok(d)
}
fn requiring_bytes(&self) -> ByteCount {
self.0.requiring_bytes()
}
fn is_idle(&self) -> bool {
self.0.is_idle()
}
}
impl MessageDecode for StdDurationDecoder {}
#[derive(Debug, Default)]
pub struct StdDurationEncoder(DurationMessageEncoder);
impl StdDurationEncoder {
pub fn new() -> Self {
Self::default()
}
}
impl Encode for StdDurationEncoder {
type Item = Duration;
fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result<usize> {
track!(self.0.encode(buf, eos))
}
fn start_encoding(&mut self, item: Self::Item) -> Result<()> {
let item = track!(DurationMessage::from_duration(item))?;
track!(self.0.start_encoding(item))
}
fn requiring_bytes(&self) -> ByteCount {
self.0.requiring_bytes()
}
fn is_idle(&self) -> bool {
self.0.is_idle()
}
}
impl SizedEncode for StdDurationEncoder {
fn exact_requiring_bytes(&self) -> u64 {
self.0.exact_requiring_bytes()
}
}
impl MessageEncode for StdDurationEncoder {}
#[cfg(test)]
mod tests {
use super::*;
use crate::field::{num::F2, MessageFieldDecoder};
use crate::message::MessageDecoder;
use bytecodec::DecodeExt;
#[test]
fn duration_decoder_works() {
let mut decoder: MessageDecoder<MessageFieldDecoder<F2, StdDurationDecoder>> =
Default::default();
let input = [18, 0];
track_try_unwrap!(decoder.decode_from_bytes(&input[..]));
}
}