use core::convert::TryFrom;
use core::str;
use serde::de::{Deserialize, Deserializer, Visitor};
use serde::ser::{Serialize, Serializer};
use std::borrow::Cow;
use crate::{Basic, Error, Result, Type};
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct Signature<'a>(Cow<'a, [u8]>);
impl<'a> Signature<'a> {
pub fn as_str(&self) -> &str {
unsafe { str::from_utf8_unchecked(&self.0) }
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn from_bytes_unchecked<'s: 'a>(bytes: &'s [u8]) -> Self {
Self(Cow::from(bytes))
}
pub fn from_str_unchecked<'s: 'a>(signature: &'s str) -> Self {
Self::from_bytes_unchecked(signature.as_bytes())
}
pub fn from_string_unchecked(signature: String) -> Self {
Self(Cow::from(signature.as_bytes().to_owned()))
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub(crate) fn to_owned(&self) -> Signature<'static> {
let s = self.0.clone().into_owned();
Signature(Cow::Owned(s))
}
}
impl<'a> Basic for Signature<'a> {
const SIGNATURE_CHAR: char = 'g';
const SIGNATURE_STR: &'static str = "g";
const ALIGNMENT: usize = 1;
}
impl<'a> Type for Signature<'a> {
fn signature() -> Signature<'static> {
Signature::from_str_unchecked(Self::SIGNATURE_STR)
}
}
impl<'a> TryFrom<&'a [u8]> for Signature<'a> {
type Error = Error;
fn try_from(value: &'a [u8]) -> Result<Self> {
ensure_correct_signature_str(value)?;
Ok(Self::from_bytes_unchecked(value))
}
}
impl<'a> TryFrom<&'a str> for Signature<'a> {
type Error = Error;
fn try_from(value: &'a str) -> Result<Self> {
Self::try_from(value.as_bytes())
}
}
impl<'a> TryFrom<String> for Signature<'a> {
type Error = Error;
fn try_from(value: String) -> Result<Self> {
ensure_correct_signature_str(value.as_bytes())?;
Ok(Self::from_string_unchecked(value))
}
}
impl<'a> From<Signature<'a>> for String {
fn from(value: Signature<'a>) -> String {
String::from(value.as_str())
}
}
impl<'a> From<&Signature<'a>> for String {
fn from(value: &Signature<'a>) -> String {
String::from(value.as_str())
}
}
impl<'a> std::ops::Deref for Signature<'a> {
type Target = str;
fn deref(&self) -> &Self::Target {
self.as_str()
}
}
impl<'a> PartialEq<&str> for Signature<'a> {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl<'a> std::fmt::Display for Signature<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.as_str().fmt(f)
}
}
impl<'a> Serialize for Signature<'a> {
fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.as_str())
}
}
impl<'de: 'a, 'a> Deserialize<'de> for Signature<'a> {
fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let visitor = SignatureVisitor;
deserializer.deserialize_str(visitor)
}
}
struct SignatureVisitor;
impl<'de> Visitor<'de> for SignatureVisitor {
type Value = Signature<'de>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a Signature")
}
#[inline]
fn visit_borrowed_str<E>(self, value: &'de str) -> core::result::Result<Signature<'de>, E>
where
E: serde::de::Error,
{
Signature::try_from(value).map_err(serde::de::Error::custom)
}
#[inline]
fn visit_str<E>(self, value: &str) -> core::result::Result<Signature<'de>, E>
where
E: serde::de::Error,
{
Signature::try_from(String::from(value)).map_err(serde::de::Error::custom)
}
}
fn ensure_correct_signature_str(signature: &[u8]) -> Result<()> {
if signature.len() > 255 {
return Err(serde::de::Error::invalid_length(
signature.len(),
&"<= 255 characters",
));
}
if signature.is_empty() {
return Ok(());
}
let (mut parsed, end) = match signature[0] as char {
crate::ARRAY_SIGNATURE_CHAR => {
if signature.len() == 1 {
return Err(serde::de::Error::invalid_length(1, &"> 1 character"));
}
(1, signature.len())
}
crate::STRUCT_SIG_START_CHAR => {
let c = *signature.last().expect("empty signature") as char;
if c != crate::STRUCT_SIG_END_CHAR {
return Err(serde::de::Error::invalid_value(
serde::de::Unexpected::Char(c),
&crate::STRUCT_SIG_END_STR,
));
}
(1, signature.len() - 1)
}
crate::DICT_ENTRY_SIG_START_CHAR => {
let c = *signature.last().expect("empty signature") as char;
if c != crate::DICT_ENTRY_SIG_END_CHAR {
return Err(serde::de::Error::invalid_value(
serde::de::Unexpected::Char(c),
&crate::DICT_ENTRY_SIG_END_STR,
));
}
(1, signature.len() - 1)
}
_ => (0, signature.len()),
};
while parsed < end {
let rest_of_signature = &signature[parsed..end];
let signature = Signature::from_bytes_unchecked(rest_of_signature);
let slice = crate::utils::slice_signature(&signature)?;
parsed += slice.len();
}
Ok(())
}