use crate::aead::chacha20_poly1305::{ChaCha20Poly1305, states::UpdatingAad};
use crate::aead::Aad as _;
use crate::aead::chacha20_poly1305::states::Updating;
use crate::{can_cast_u32, Unspecified};
#[cfg_attr(all(feature = "embedded-io", not(feature = "std")), doc = "# use embedded_io::Write;")]
#[cfg_attr(feature = "std", doc = "# use std::io::Write;")]
#[cfg_attr(
all(feature = "embedded-io", not(feature = "std")),
doc = "# fn main() -> Result<(), wolf_crypto::Unspecified> {"
)]
#[cfg_attr(feature = "std", doc = "# fn main() -> Result<(), Box<dyn std::error::Error>> {")]
#[must_use]
pub struct Aad<S: UpdatingAad, IO> {
aad: ChaCha20Poly1305<S>,
io: IO
}
impl<S: UpdatingAad, IO> Aad<S, IO> {
pub const fn new(aad: ChaCha20Poly1305<S>, io: IO) -> Self {
Self { aad, io }
}
#[cfg_attr(all(feature = "embedded-io", not(feature = "std")), doc = "use embedded_io::Write;")]
#[cfg_attr(feature = "std", doc = "use std::io::Write;")]
#[cfg_attr(
all(feature = "embedded-io", not(feature = "std")),
doc = "# fn main() -> Result<(), wolf_crypto::Unspecified> {"
)]
#[cfg_attr(feature = "std", doc = "# fn main() -> Result<(), Box<dyn std::error::Error>> {")]
#[inline]
pub fn finish(self) -> (ChaCha20Poly1305<S::Mode>, IO) {
(self.aad.finish(), self.io)
}
}
std! {
use std::io as std_io;
impl<S, IO> std_io::Write for Aad<S, IO>
where
S: UpdatingAad,
IO: std_io::Write
{
#[inline]
fn write(&mut self, buf: &[u8]) -> std_io::Result<usize> {
if !buf.is_valid_size() { return Err(std_io::Error::other(Unspecified)) }
self.io.write(buf).map(
|amount| unsafe { self.aad.update_aad_unchecked(&buf[..amount]); amount }
)
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> std_io::Result<()> {
if !buf.is_valid_size() { return Err(std_io::Error::other(Unspecified)) }
self.io.write_all(buf).map(|()| unsafe { self.aad.update_aad_unchecked(buf) })
}
#[inline]
fn flush(&mut self) -> std_io::Result<()> {
self.io.flush()
}
}
impl<S, IO> std_io::Read for Aad<S, IO>
where
S: UpdatingAad,
IO: std_io::Read
{
#[inline]
fn read(&mut self, buf: &mut [u8]) -> std_io::Result<usize> {
if !buf.is_valid_size() { return Err(std_io::Error::other(Unspecified)) }
match self.io.read(buf) {
Ok(read) => {
unsafe { self.aad.update_aad_unchecked(&buf[..read]); }
Ok(read)
},
res @ Err(_) => res
}
}
#[inline]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> std_io::Result<usize> {
if !buf.is_valid_size() { return Err(std_io::Error::other(Unspecified)) }
let init_len = buf.len();
match self.io.read_to_end(buf) {
Ok(read) => {
unsafe {
self.aad.update_aad_unchecked(&buf.as_mut_slice()[init_len..init_len + read])
};
Ok(read)
},
res @ Err(_) => res
}
}
}
}
no_std_io! {
use embedded_io::{self as eio, ErrorType};
impl<S: UpdatingAad, IO> ErrorType for Aad<S, IO> {
type Error = Unspecified;
}
impl<S, IO> eio::Write for Aad<S, IO>
where
S: UpdatingAad,
IO: eio::Write
{
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
if !buf.is_valid_size() { return Err(Unspecified) }
match self.io.write(buf) {
Ok(amount) => {
unsafe { self.aad.update_aad_unchecked(&buf[..amount]); }
Ok(amount)
},
Err(_) => Err(Unspecified)
}
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
if !buf.is_valid_size() { return Err(Unspecified) }
match self.io.write_all(buf) {
Ok(()) => {
unsafe { self.aad.update_aad_unchecked(buf); }
Ok(())
},
Err(_) => Err(Unspecified)
}
}
#[inline]
fn flush(&mut self) -> Result<(), Self::Error> {
self.io.flush().map_err(|_| Unspecified)
}
}
impl<S, IO> eio::Read for Aad<S, IO>
where
S: UpdatingAad,
IO: eio::Read
{
#[inline]
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
if !buf.is_valid_size() { return Err(Unspecified) }
match self.io.read(buf) {
Ok(read) => {
unsafe { self.aad.update_aad_unchecked(&buf[..read]); }
Ok(read)
},
Err(_) => Err(Unspecified)
}
}
}
}
#[cfg_attr(all(feature = "embedded-io", not(feature = "std")), doc = "# use embedded_io::Read;")]
#[cfg_attr(feature = "std", doc = "# use std::io::Read;")]
#[cfg_attr(
all(feature = "embedded-io", not(feature = "std")),
doc = "# fn main() -> Result<(), wolf_crypto::Unspecified> {"
)]
#[cfg_attr(feature = "std", doc = "# fn main() -> Result<(), Box<dyn std::error::Error>> {")]
#[must_use]
pub struct Data<S: Updating, IO> {
aead: ChaCha20Poly1305<S>,
io: IO
}
impl<S: Updating, IO> Data<S, IO> {
pub const fn new(aead: ChaCha20Poly1305<S>, io: IO) -> Self {
Self { aead, io }
}
#[cfg_attr(all(feature = "embedded-io", not(feature = "std")), doc = "# use embedded_io::Read;")]
#[cfg_attr(feature = "std", doc = "# use std::io::Read;")]
#[cfg_attr(
all(feature = "embedded-io", not(feature = "std")),
doc = "# fn main() -> Result<(), wolf_crypto::Unspecified> {"
)]
#[cfg_attr(feature = "std", doc = "# fn main() -> Result<(), Box<dyn std::error::Error>> {")]
#[inline]
pub fn finish(self) -> (ChaCha20Poly1305<S>, IO) {
(self.aead, self.io)
}
}
std! {
impl<S, IO> std_io::Read for Data<S, IO>
where
S: Updating,
IO: std_io::Read
{
#[inline]
fn read(&mut self, buf: &mut [u8]) -> std_io::Result<usize> {
if !can_cast_u32(buf.len()) { return Err(std_io::Error::other(Unspecified)) }
self.io.read(buf).map(|amount| unsafe {
self.aead.update_in_place_unchecked(&mut buf[..amount]);
amount
})
}
}
}
no_std_io! {
impl<S: Updating, IO: ErrorType> ErrorType for Data<S, IO> {
type Error = Unspecified;
}
impl<S, IO> eio::Read for Data<S, IO>
where
S: Updating,
IO: eio::Read
{
#[inline]
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
if !can_cast_u32(buf.len()) { return Err(Unspecified) }
match self.io.read(buf) {
Ok(amount) => {
unsafe { self.aead.update_in_place_unchecked(&mut buf[..amount]) };
Ok(amount)
},
Err(_) => Err(Unspecified)
}
}
}
}