use std;
use byteorder::{ByteOrder, LittleEndian};
use trackable::error::ErrorKindExt;
use {ErrorKind, Result};
use traits::{FieldType, MapKey, Message, Packable, TryFrom};
use wire::WireType;
use wire::types::{Bit32, Bit64, LengthDelimited, Varint};
macro_rules! impl_scalar_type {
($t:ident, $base:ty, $wire:ident) => {
impl FieldType for $t {
fn wire_type() -> WireType {
WireType::$wire
}
}
impl From<$base> for $t {
fn from(f: $base) -> Self {
$t(f)
}
}
impl From<$t> for $base {
fn from(f: $t) -> Self {
f.0
}
}
}
}
#[derive(Debug, Default)]
pub struct Bool(pub bool);
impl_scalar_type!(Bool, bool, Varint);
impl Packable for Bool {}
impl TryFrom<Varint> for Bool {
fn try_from(f: Varint) -> Result<Self> {
track_assert!(
f.0 <= 1,
ErrorKind::Invalid,
"Tool large `bool` value: {}",
f.0
);
Ok(Bool(f.0 != 0))
}
}
impl MapKey for Bool {}
#[derive(Debug, Default)]
pub struct Int32(pub i32);
impl_scalar_type!(Int32, i32, Varint);
impl Packable for Int32 {}
impl TryFrom<Varint> for Int32 {
fn try_from(f: Varint) -> Result<Self> {
let n = f.0 as i64;
track_assert!(
n >= i64::from(std::i32::MIN),
ErrorKind::Invalid,
"Tool small `int32` value: {}",
n
);
track_assert!(
n <= i64::from(std::i32::MAX),
ErrorKind::Invalid,
"Tool large `int32` value: {}",
n
);
Ok(Int32(f.0 as i32))
}
}
impl MapKey for Int32 {}
#[derive(Debug, Default)]
pub struct Int64(pub i64);
impl_scalar_type!(Int64, i64, Varint);
impl Packable for Int64 {}
impl From<Varint> for Int64 {
fn from(f: Varint) -> Self {
Int64(f.0 as i64)
}
}
impl MapKey for Int64 {}
#[derive(Debug, Default)]
pub struct Uint32(pub u32);
impl_scalar_type!(Uint32, u32, Varint);
impl Packable for Uint32 {}
impl TryFrom<Varint> for Uint32 {
fn try_from(f: Varint) -> Result<Self> {
track_assert!(
f.0 <= u64::from(std::u32::MAX),
ErrorKind::Invalid,
"Tool large `uint32` value: {}",
f.0
);
Ok(Uint32(f.0 as u32))
}
}
impl MapKey for Uint32 {}
#[derive(Debug, Default)]
pub struct Uint64(pub u64);
impl_scalar_type!(Uint64, u64, Varint);
impl Packable for Uint64 {}
impl From<Varint> for Uint64 {
fn from(f: Varint) -> Self {
Uint64(f.0)
}
}
impl MapKey for Uint64 {}
#[derive(Debug, Default)]
pub struct Sint32(pub i32);
impl_scalar_type!(Sint32, i32, Varint);
impl Packable for Sint32 {}
impl TryFrom<Varint> for Sint32 {
fn try_from(f: Varint) -> Result<Self> {
let n = ((f.0 << 63) | (f.0 >> 1)) as i64;
track_assert!(
n >= i64::from(std::i32::MIN),
ErrorKind::Invalid,
"Tool small `int32` value: {}",
n
);
track_assert!(
n <= i64::from(std::i32::MAX),
ErrorKind::Invalid,
"Tool large `int32` value: {}",
n
);
Ok(Sint32(n as i32))
}
}
impl MapKey for Sint32 {}
#[derive(Debug, Default)]
pub struct Sint64(pub i64);
impl_scalar_type!(Sint64, i64, Varint);
impl Packable for Sint64 {}
impl From<Varint> for Sint64 {
fn from(f: Varint) -> Self {
let n = ((f.0 << 63) | (f.0 >> 1)) as i64;
Sint64(n)
}
}
impl MapKey for Sint64 {}
#[derive(Debug, Default)]
pub struct Fixed32(pub u32);
impl_scalar_type!(Fixed32, u32, Bit32);
impl Packable for Fixed32 {}
impl From<Bit32> for Fixed32 {
fn from(f: Bit32) -> Self {
Fixed32(LittleEndian::read_u32(&f.0[..]))
}
}
impl MapKey for Fixed32 {}
#[derive(Debug, Default)]
pub struct Fixed64(pub u64);
impl_scalar_type!(Fixed64, u64, Bit64);
impl Packable for Fixed64 {}
impl From<Bit64> for Fixed64 {
fn from(f: Bit64) -> Self {
Fixed64(LittleEndian::read_u64(&f.0[..]))
}
}
impl MapKey for Fixed64 {}
#[derive(Debug, Default)]
pub struct Sfixed32(pub i32);
impl_scalar_type!(Sfixed32, i32, Bit32);
impl Packable for Sfixed32 {}
impl From<Bit32> for Sfixed32 {
fn from(f: Bit32) -> Self {
Sfixed32(LittleEndian::read_i32(&f.0[..]))
}
}
impl MapKey for Sfixed32 {}
#[derive(Debug, Default)]
pub struct Sfixed64(pub i64);
impl_scalar_type!(Sfixed64, i64, Bit64);
impl Packable for Sfixed64 {}
impl From<Bit64> for Sfixed64 {
fn from(f: Bit64) -> Self {
Sfixed64(LittleEndian::read_i64(&f.0[..]))
}
}
impl MapKey for Sfixed64 {}
#[derive(Debug, Default)]
pub struct Float(pub f32);
impl_scalar_type!(Float, f32, Bit32);
impl Packable for Float {}
impl From<Bit32> for Float {
fn from(f: Bit32) -> Self {
Float(LittleEndian::read_f32(&f.0[..]))
}
}
#[derive(Debug, Default)]
pub struct Double(pub f64);
impl_scalar_type!(Double, f64, Bit64);
impl Packable for Double {}
impl From<Bit64> for Double {
fn from(f: Bit64) -> Self {
Double(LittleEndian::read_f64(&f.0[..]))
}
}
#[derive(Debug, Default)]
pub struct Bytes(pub Vec<u8>);
impl_scalar_type!(Bytes, Vec<u8>, LengthDelimited);
impl From<LengthDelimited<Vec<u8>>> for Bytes {
fn from(f: LengthDelimited<Vec<u8>>) -> Self {
Bytes(f.0)
}
}
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Str(pub String);
impl_scalar_type!(Str, String, LengthDelimited);
impl TryFrom<Bytes> for Str {
fn try_from(f: Bytes) -> Result<Str> {
String::from_utf8(f.0)
.map(Str)
.map_err(|e| ErrorKind::Invalid.cause(e))
}
}
impl MapKey for Str {}
#[derive(Debug, Default)]
pub struct Embedded<T: Message>(pub(crate) T::Base);
impl<T: Message> Embedded<T> {
pub fn new(message: T) -> Self {
Embedded(message.into_base())
}
pub fn unwrap(self) -> Result<T> {
T::from_base(self.0)
}
}
impl<T: Message> FieldType for Embedded<T> {
fn wire_type() -> WireType {
WireType::LengthDelimited
}
}
impl<T: Message> From<T> for Embedded<T> {
fn from(f: T) -> Self {
Embedded(f.into_base())
}
}