diff --git a/rbx_asset/src/types.rs b/rbx_asset/src/types.rs index b9ef790..2aa64f5 100644 --- a/rbx_asset/src/types.rs +++ b/rbx_asset/src/types.rs @@ -16,3 +16,53 @@ impl std::fmt::Display for ResponseError{ } } impl std::error::Error for ResponseError{} + +#[cfg(feature="gzip")] +use std::io::Cursor; +#[cfg(feature="gzip")] +use flate2::read::GzDecoder; + +/// Some bytes that might be gzipped. Use the read_with or to_vec methods to transparently decode gzip. +pub struct MaybeGzippedBytes{ + bytes:bytes::Bytes, +} +impl MaybeGzippedBytes{ + pub(crate) fn new(bytes:bytes::Bytes)->Self{ + Self{bytes} + } + pub fn into_inner(self)->bytes::Bytes{ + self.bytes + } + /// get a reference to the bytes, ignoring gzip decoding + pub fn as_raw_ref(&self)->&[u8]{ + self.bytes.as_ref() + } + /// Transparently decode gzip data, if present (intermediate allocation) + #[cfg(feature="gzip")] + pub fn to_vec(&self)->std::io::Result<Vec<u8>>{ + use std::io::Read; + match self.bytes.get(0..2){ + Some(b"\x1f\x8b")=>{ + let mut buf=Vec::new(); + GzDecoder::new(Cursor::new(self.bytes.as_ref())).read_to_end(&mut buf)?; + Ok(buf) + }, + _=>Ok(self.bytes.to_vec()) + } + } + /// Read the bytes with the provided decoders. + /// The idea is to make a function that is generic over std::io::Read + /// and pass the same function to both closures. + /// This two closure hack must be done because of the different concrete types. + #[cfg(feature="gzip")] + pub fn read_with<'a,ReadGzip,ReadRaw,T>(&'a self,read_gzip:ReadGzip,read_raw:ReadRaw)->T + where + ReadGzip:Fn(GzDecoder<Cursor<&'a [u8]>>)->T, + ReadRaw:Fn(Cursor<&'a [u8]>)->T, + { + match self.bytes.get(0..2){ + Some(b"\x1f\x8b")=>read_gzip(GzDecoder::new(Cursor::new(self.bytes.as_ref()))), + _=>read_raw(Cursor::new(self.bytes.as_ref())) + } + } +} diff --git a/rbx_asset/src/util.rs b/rbx_asset/src/util.rs index 6b2b23e..9f8a785 100644 --- a/rbx_asset/src/util.rs +++ b/rbx_asset/src/util.rs @@ -17,56 +17,6 @@ pub(crate) async fn response_ok(response:reqwest::Response)->Result<reqwest::Res } } -#[cfg(feature="gzip")] -use std::io::Cursor; -#[cfg(feature="gzip")] -use flate2::read::GzDecoder; - -/// Some bytes that might be gzipped. Use the read_with or to_vec methods to transparently decode gzip. -pub struct MaybeGzippedBytes{ - bytes:bytes::Bytes, -} -impl MaybeGzippedBytes{ - pub(crate) fn new(bytes:bytes::Bytes)->Self{ - Self{bytes} - } - pub fn into_inner(self)->bytes::Bytes{ - self.bytes - } - /// get a reference to the bytes, ignoring gzip decoding - pub fn as_raw_ref(&self)->&[u8]{ - self.bytes.as_ref() - } - /// Transparently decode gzip data, if present (intermediate allocation) - #[cfg(feature="gzip")] - pub fn to_vec(&self)->std::io::Result<Vec<u8>>{ - use std::io::Read; - match self.bytes.get(0..2){ - Some(b"\x1f\x8b")=>{ - let mut buf=Vec::new(); - GzDecoder::new(Cursor::new(self.bytes.as_ref())).read_to_end(&mut buf)?; - Ok(buf) - }, - _=>Ok(self.bytes.to_vec()) - } - } - /// Read the bytes with the provided decoders. - /// The idea is to make a function that is generic over std::io::Read - /// and pass the same function to both closures. - /// This two closure hack must be done because of the different concrete types. - #[cfg(feature="gzip")] - pub fn read_with<'a,ReadGzip,ReadRaw,T>(&'a self,read_gzip:ReadGzip,read_raw:ReadRaw)->T - where - ReadGzip:Fn(GzDecoder<Cursor<&'a [u8]>>)->T, - ReadRaw:Fn(Cursor<&'a [u8]>)->T, - { - match self.bytes.get(0..2){ - Some(b"\x1f\x8b")=>read_gzip(GzDecoder::new(Cursor::new(self.bytes.as_ref()))), - _=>read_raw(Cursor::new(self.bytes.as_ref())) - } - } -} - use serde::de::{Error,Unexpected}; use serde::{Deserializer,Serializer};