From 5b80b10949450d36bb922783d0345e01c3fe26c3 Mon Sep 17 00:00:00 2001 From: meh Date: Sun, 24 May 2015 18:51:34 +0200 Subject: [PATCH] util/error: refactor error handling --- src/codec/context.rs | 12 +- src/codec/decoder/audio.rs | 2 +- src/codec/decoder/mod.rs | 6 +- src/codec/decoder/subtitle.rs | 2 +- src/codec/decoder/video.rs | 2 +- src/codec/encoder/audio.rs | 2 +- src/codec/encoder/mod.rs | 6 +- src/codec/encoder/subtitle.rs | 2 +- src/codec/encoder/video.rs | 2 +- src/codec/picture.rs | 12 +- src/device/extensions.rs | 2 +- src/format/context.rs | 24 ++-- src/util/error.rs | 232 ++++++++++++++++++++++++---------- 13 files changed, 205 insertions(+), 101 deletions(-) diff --git a/src/codec/context.rs b/src/codec/context.rs index 87c2181..d17b47a 100644 --- a/src/codec/context.rs +++ b/src/codec/context.rs @@ -30,7 +30,7 @@ impl Context { unsafe { match avcodec_open2(self.ptr, codec.ptr, ptr::null_mut()) { 0 => Ok(Opened(self)), - e => Err(Error::new(e)) + e => Err(Error::from(e)) } } } @@ -39,7 +39,7 @@ impl Context { unsafe { match avcodec_open2(self.ptr, codec.ptr, &mut options.ptr) { 0 => Ok(Opened(self)), - e => Err(Error::new(e)) + e => Err(Error::from(e)) } } } @@ -49,7 +49,7 @@ impl Context { self.clone().open(codec).and_then(|c| c.decoder()) } else { - Err(Error::from(AVERROR_DECODER_NOT_FOUND)) + Err(Error::DecoderNotFound) } } @@ -58,7 +58,7 @@ impl Context { self.clone().open(codec).and_then(|c| c.encoder()) } else { - Err(Error::from(AVERROR_ENCODER_NOT_FOUND)) + Err(Error::EncoderNotFound) } } @@ -169,7 +169,7 @@ impl Opened { Ok(Decoder(self)) } else { - Err(Error::from(AVERROR_INVALIDDATA)) + Err(Error::InvalidData) } } @@ -184,7 +184,7 @@ impl Opened { Ok(Encoder(self)) } else { - Err(Error::from(AVERROR_INVALIDDATA)) + Err(Error::InvalidData) } } } diff --git a/src/codec/decoder/audio.rs b/src/codec/decoder/audio.rs index b1dbb90..aeeb8b2 100644 --- a/src/codec/decoder/audio.rs +++ b/src/codec/decoder/audio.rs @@ -16,7 +16,7 @@ impl Audio { let mut got: c_int = 0; match avcodec_decode_audio4(self.ptr, out.ptr, &mut got, &packet.val) { - e if e < 0 => Err(Error::new(e)), + e if e < 0 => Err(Error::from(e)), _ => Ok(got != 0) } } diff --git a/src/codec/decoder/mod.rs b/src/codec/decoder/mod.rs index 914e6e2..d615870 100644 --- a/src/codec/decoder/mod.rs +++ b/src/codec/decoder/mod.rs @@ -34,7 +34,7 @@ impl Decoder { Ok(Video(self)) } else { - Err(Error::from(AVERROR_INVALIDDATA)) + Err(Error::InvalidData) } } @@ -43,7 +43,7 @@ impl Decoder { Ok(Audio(self)) } else { - Err(Error::from(AVERROR_INVALIDDATA)) + Err(Error::InvalidData) } } @@ -52,7 +52,7 @@ impl Decoder { Ok(Subtitle(self)) } else { - Err(Error::from(AVERROR_INVALIDDATA)) + Err(Error::InvalidData) } } diff --git a/src/codec/decoder/subtitle.rs b/src/codec/decoder/subtitle.rs index 88a5190..ac4341a 100644 --- a/src/codec/decoder/subtitle.rs +++ b/src/codec/decoder/subtitle.rs @@ -14,7 +14,7 @@ impl Subtitle { let mut got: c_int = 0; match avcodec_decode_subtitle2(self.ptr, &mut out.val, &mut got, &packet.val) { - e if e < 0 => Err(Error::new(e)), + e if e < 0 => Err(Error::from(e)), _ => Ok(got != 0) } } diff --git a/src/codec/decoder/video.rs b/src/codec/decoder/video.rs index 472b7ea..e18bb5f 100644 --- a/src/codec/decoder/video.rs +++ b/src/codec/decoder/video.rs @@ -18,7 +18,7 @@ impl Video { let mut got: c_int = 0; match avcodec_decode_video2(self.ptr, out.ptr, &mut got, &packet.val) { - e if e < 0 => Err(Error::new(e)), + e if e < 0 => Err(Error::from(e)), _ => Ok(got != 0) } } diff --git a/src/codec/encoder/audio.rs b/src/codec/encoder/audio.rs index 8960b3d..03587fc 100644 --- a/src/codec/encoder/audio.rs +++ b/src/codec/encoder/audio.rs @@ -15,7 +15,7 @@ impl Audio { let mut got: c_int = 0; match avcodec_encode_audio2(self.ptr, &mut out.val, frame.ptr, &mut got) { - e if e < 0 => Err(Error::new(e)), + e if e < 0 => Err(Error::from(e)), _ => Ok(got != 0) } } diff --git a/src/codec/encoder/mod.rs b/src/codec/encoder/mod.rs index 664cc24..9c9e89a 100644 --- a/src/codec/encoder/mod.rs +++ b/src/codec/encoder/mod.rs @@ -38,7 +38,7 @@ impl Encoder { Ok(Video(self)) } else { - Err(Error::from(AVERROR_INVALIDDATA)) + Err(Error::InvalidData) } } @@ -47,7 +47,7 @@ impl Encoder { Ok(Audio(self)) } else { - Err(Error::from(AVERROR_INVALIDDATA)) + Err(Error::InvalidData) } } @@ -56,7 +56,7 @@ impl Encoder { Ok(Subtitle(self)) } else { - Err(Error::from(AVERROR_INVALIDDATA)) + Err(Error::InvalidData) } } diff --git a/src/codec/encoder/subtitle.rs b/src/codec/encoder/subtitle.rs index fb0cec0..4e8bc22 100644 --- a/src/codec/encoder/subtitle.rs +++ b/src/codec/encoder/subtitle.rs @@ -12,7 +12,7 @@ impl Subtitle { pub fn encode(&self, subtitle: &::Subtitle, out: &mut [u8]) -> Result { unsafe { match avcodec_encode_subtitle(self.ptr, out.as_mut_ptr(), out.len() as c_int, &subtitle.val) { - e if e < 0 => Err(Error::new(e)), + e if e < 0 => Err(Error::from(e)), _ => Ok(true) } } diff --git a/src/codec/encoder/video.rs b/src/codec/encoder/video.rs index b18a5e4..15069ab 100644 --- a/src/codec/encoder/video.rs +++ b/src/codec/encoder/video.rs @@ -16,7 +16,7 @@ impl Video { let mut got: c_int = 0; match avcodec_encode_video2(self.ptr, &mut out.val, frame.ptr, &mut got) { - e if e < 0 => Err(Error::new(e)), + e if e < 0 => Err(Error::from(e)), _ => Ok(got != 0) } } diff --git a/src/codec/picture.rs b/src/codec/picture.rs index f3b0dca..9ffadef 100644 --- a/src/codec/picture.rs +++ b/src/codec/picture.rs @@ -23,7 +23,7 @@ impl<'a> Picture<'a> { unsafe { match avpicture_get_size(format.into(), width as c_int, height as c_int) { v if v >= 0 => Ok(v as usize), - e => Err(Error::new(e)) + e => Err(Error::from(e)) } } } @@ -44,7 +44,7 @@ impl<'a> Picture<'a> { _marker: PhantomData }), - e => Err(Error::new(e)) + e => Err(Error::from(e)) } } } @@ -78,7 +78,7 @@ impl<'a> Picture<'a> { unsafe { match avpicture_layout(self.ptr, self.format.into(), self.width as c_int, self.height as c_int, out.as_mut_ptr(), out.len() as c_int) { s if s >= 0 => Ok(s as usize), - e => Err(Error::new(e)) + e => Err(Error::from(e)) } } } @@ -87,20 +87,20 @@ impl<'a> Picture<'a> { unsafe { match avpicture_layout(self.ptr, format.into(), width as c_int, height as c_int, out.as_mut_ptr(), out.len() as c_int) { s if s >= 0 => Ok(s as usize), - e => Err(Error::new(e)) + e => Err(Error::from(e)) } } } pub fn crop(&mut self, source: &Picture, top: u32, left: u32) -> Result<(), Error> { if self.format != source.format { - return Err(Error::new(AVERROR_BUG)); + return Err(Error::Bug); } unsafe { match av_picture_crop(self.ptr, source.ptr, self.format.into(), top as c_int, left as c_int) { 0 => Ok(()), - e => Err(Error::new(e)) + e => Err(Error::from(e)) } } } diff --git a/src/device/extensions.rs b/src/device/extensions.rs index 0e78a7e..438e832 100644 --- a/src/device/extensions.rs +++ b/src/device/extensions.rs @@ -27,7 +27,7 @@ impl<'a> DeviceIter<'a> { match avdevice_list_devices(ctx, &mut ptr) { n if n < 0 => - Err(Error::new(n)), + Err(Error::from(n)), _ => Ok(DeviceIter { ptr: ptr, cur: 0, _marker: PhantomData }) diff --git a/src/format/context.rs b/src/format/context.rs index 95cd667..d877e05 100644 --- a/src/format/context.rs +++ b/src/format/context.rs @@ -159,7 +159,7 @@ impl<'a> Packet<'a> { unsafe { match av_read_frame(self.ptr, &mut self.pkt.val) { 0 => Ok(()), - e => Err(Error::new(e)) + e => Err(Error::from(e)) } } } @@ -169,7 +169,7 @@ impl<'a> Packet<'a> { match av_write_frame(self.ptr, &mut self.pkt.val) { 1 => Ok(true), 0 => Ok(false), - e => Err(Error::new(e)) + e => Err(Error::from(e)) } } } @@ -224,11 +224,11 @@ pub fn open(path: &Path) -> Result { match avformat_find_stream_info(ps, ptr::null_mut()) { 0 => Ok(ctx), - e => Err(Error::new(e)) + e => Err(Error::from(e)) } }, - e => Err(Error::new(e)) + e => Err(Error::from(e)) } } } @@ -248,11 +248,11 @@ pub fn open_with(path: &Path, mut options: Dictionary) -> Result match avformat_find_stream_info(ps, ptr::null_mut()) { 0 => Ok(ctx), - e => Err(Error::new(e)) + e => Err(Error::from(e)) } }, - e => Err(Error::new(e)) + e => Err(Error::from(e)) } } } @@ -270,16 +270,16 @@ pub fn open_as(path: &Path, format: &Format) -> Result { match avformat_find_stream_info(ps, ptr::null_mut()) { 0 => Ok(ctx), - e => Err(Error::new(e)) + e => Err(Error::from(e)) } }, - e => Err(Error::new(e)) + e => Err(Error::from(e)) } } } else { - Err(Error::new(AVERROR_BUG)) + Err(Error::Bug) } } @@ -299,16 +299,16 @@ pub fn open_as_with(path: &Path, format: &Format, mut options: Dictionary) -> Re match avformat_find_stream_info(ps, ptr::null_mut()) { 0 => Ok(ctx), - e => Err(Error::new(e)) + e => Err(Error::from(e)) } }, - e => Err(Error::new(e)) + e => Err(Error::from(e)) } } } else { - Err(Error::new(AVERROR_BUG)) + Err(Error::Bug) } } diff --git a/src/util/error.rs b/src/util/error.rs index e56cf7e..cb1a76d 100644 --- a/src/util/error.rs +++ b/src/util/error.rs @@ -1,76 +1,150 @@ use std::error; use std::fmt; -use std::cell::RefCell; use std::ffi::CStr; use std::str::from_utf8_unchecked; use libc::c_int; use ffi::*; -pub struct Error { - code: c_int, - desc: RefCell>, +#[derive(Copy, Clone)] +pub enum Error { + Bug, + Bug2, + Unknown, + Experimental, + BufferTooSmall, + Eof, + Exit, + External, + InvalidData, + PatchWelcome, + + InputChanged, + OutputChanged, + + BsfNotFound, + DecoderNotFound, + DemuxerNotFound, + EncoderNotFound, + OptionNotFound, + MuxerNotFound, + FilterNotFound, + ProtocolNotFound, + StreamNotFound, + + HttpBadRequest, + HttpUnauthorized, + HttpForbidden, + HttpNotFound, + HttpOther4xx, + HttpServerError, } impl Error { - pub fn new(code: c_int) -> Self { - Error { code: code, desc: RefCell::new(None) } - } - - pub fn bug() -> Self { - Self::new(AVERROR_BUG) - } - - pub fn eof() -> Self { - Self::new(AVERROR_EOF) - } - - pub fn exit() -> Self { - Self::new(AVERROR_EXIT) - } - - pub fn external() -> Self { - Self::new(AVERROR_EXTERNAL) - } - - pub fn experimental() -> Self { - Self::new(AVERROR_EXPERIMENTAL) - } - - pub fn unknown() -> Self { - Self::new(AVERROR_UNKNOWN) - } - - pub fn invalid() -> Self { - Self::new(AVERROR_INVALIDDATA) - } -} - -unsafe impl Send for Error { } - -impl Clone for Error { - fn clone(&self) -> Self { - if let Some(old) = *self.desc.borrow() { - Error { - code: self.code, - desc: RefCell::new(Some(old)), - } - } - else { - Error { - code: self.code, - desc: RefCell::new(None), - } + pub fn index(self) -> usize { + match self { + Error::BsfNotFound => 0, + Error::Bug => 1, + Error::BufferTooSmall => 2, + Error::DecoderNotFound => 3, + Error::DemuxerNotFound => 4, + Error::EncoderNotFound => 5, + Error::Eof => 6, + Error::Exit => 7, + Error::External => 8, + Error::FilterNotFound => 9, + Error::InvalidData => 10, + Error::MuxerNotFound => 11, + Error::OptionNotFound => 12, + Error::PatchWelcome => 13, + Error::ProtocolNotFound => 14, + Error::StreamNotFound => 15, + Error::Bug2 => 16, + Error::Unknown => 17, + Error::Experimental => 18, + Error::InputChanged => 19, + Error::OutputChanged => 20, + Error::HttpBadRequest => 21, + Error::HttpUnauthorized => 22, + Error::HttpForbidden => 23, + Error::HttpNotFound => 24, + Error::HttpOther4xx => 25, + Error::HttpServerError => 26, } } } impl From for Error { fn from(value: c_int) -> Error { - Error::new(value) + match value { + AVERROR_BSF_NOT_FOUND => Error::BsfNotFound, + AVERROR_BUG => Error::Bug, + AVERROR_BUFFER_TOO_SMALL => Error::BufferTooSmall, + AVERROR_DECODER_NOT_FOUND => Error::DecoderNotFound, + AVERROR_DEMUXER_NOT_FOUND => Error::DemuxerNotFound, + AVERROR_ENCODER_NOT_FOUND => Error::EncoderNotFound, + AVERROR_EOF => Error::Eof, + AVERROR_EXIT => Error::Exit, + AVERROR_EXTERNAL => Error::External, + AVERROR_FILTER_NOT_FOUND => Error::FilterNotFound, + AVERROR_INVALIDDATA => Error::InvalidData, + AVERROR_MUXER_NOT_FOUND => Error::MuxerNotFound, + AVERROR_OPTION_NOT_FOUND => Error::OptionNotFound, + AVERROR_PATCHWELCOME => Error::PatchWelcome, + AVERROR_PROTOCOL_NOT_FOUND => Error::ProtocolNotFound, + AVERROR_STREAM_NOT_FOUND => Error::StreamNotFound, + AVERROR_BUG2 => Error::Bug2, + AVERROR_UNKNOWN => Error::Unknown, + AVERROR_EXPERIMENTAL => Error::Experimental, + AVERROR_INPUT_CHANGED => Error::InputChanged, + AVERROR_OUTPUT_CHANGED => Error::OutputChanged, + AVERROR_HTTP_BAD_REQUEST => Error::HttpBadRequest, + AVERROR_HTTP_UNAUTHORIZED => Error::HttpUnauthorized, + AVERROR_HTTP_FORBIDDEN => Error::HttpForbidden, + AVERROR_HTTP_NOT_FOUND => Error::HttpNotFound, + AVERROR_HTTP_OTHER_4XX => Error::HttpOther4xx, + AVERROR_HTTP_SERVER_ERROR => Error::HttpServerError, + + _ => Error::Unknown + } } } +impl Into for Error { + fn into(self) -> c_int { + match self { + Error::BsfNotFound => AVERROR_BSF_NOT_FOUND, + Error::Bug => AVERROR_BUG, + Error::BufferTooSmall => AVERROR_BUFFER_TOO_SMALL, + Error::DecoderNotFound => AVERROR_DECODER_NOT_FOUND, + Error::DemuxerNotFound => AVERROR_DEMUXER_NOT_FOUND, + Error::EncoderNotFound => AVERROR_ENCODER_NOT_FOUND, + Error::Eof => AVERROR_EOF, + Error::Exit => AVERROR_EXIT, + Error::External => AVERROR_EXTERNAL, + Error::FilterNotFound => AVERROR_FILTER_NOT_FOUND, + Error::InvalidData => AVERROR_INVALIDDATA, + Error::MuxerNotFound => AVERROR_MUXER_NOT_FOUND, + Error::OptionNotFound => AVERROR_OPTION_NOT_FOUND, + Error::PatchWelcome => AVERROR_PATCHWELCOME, + Error::ProtocolNotFound => AVERROR_PROTOCOL_NOT_FOUND, + Error::StreamNotFound => AVERROR_STREAM_NOT_FOUND, + Error::Bug2 => AVERROR_BUG2, + Error::Unknown => AVERROR_UNKNOWN, + Error::Experimental => AVERROR_EXPERIMENTAL, + Error::InputChanged => AVERROR_INPUT_CHANGED, + Error::OutputChanged => AVERROR_OUTPUT_CHANGED, + Error::HttpBadRequest => AVERROR_HTTP_BAD_REQUEST, + Error::HttpUnauthorized => AVERROR_HTTP_UNAUTHORIZED, + Error::HttpForbidden => AVERROR_HTTP_FORBIDDEN, + Error::HttpNotFound => AVERROR_HTTP_NOT_FOUND, + Error::HttpOther4xx => AVERROR_HTTP_OTHER_4XX, + Error::HttpServerError => AVERROR_HTTP_SERVER_ERROR, + } + } +} + + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { f.write_str(error::Error::description(self)) @@ -80,25 +154,55 @@ impl fmt::Display for Error { impl fmt::Debug for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { try!(f.write_str("ffmpeg::Error(")); - try!(f.write_str(&format!("{}: ", AVUNERROR(self.code)))); + try!(f.write_str(&format!("{}: ", AVUNERROR((*self).into())))); try!(fmt::Display::fmt(self, f)); f.write_str(")") } } +// XXX: the length has to be synced with the number of errors +static mut STRINGS: [[i8; AV_ERROR_MAX_STRING_SIZE as usize]; 27] + = [[0i8; AV_ERROR_MAX_STRING_SIZE as usize]; 27]; + +pub fn register_all() { + unsafe { + av_strerror(Error::Bug.into(), STRINGS[Error::Bug.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::Bug2.into(), STRINGS[Error::Bug2.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::Unknown.into(), STRINGS[Error::Unknown.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::Experimental.into(), STRINGS[Error::Experimental.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::BufferTooSmall.into(), STRINGS[Error::BufferTooSmall.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::Eof.into(), STRINGS[Error::Eof.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::Exit.into(), STRINGS[Error::Exit.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::External.into(), STRINGS[Error::External.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::InvalidData.into(), STRINGS[Error::InvalidData.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::PatchWelcome.into(), STRINGS[Error::PatchWelcome.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + + av_strerror(Error::InputChanged.into(), STRINGS[Error::InputChanged.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::OutputChanged.into(), STRINGS[Error::OutputChanged.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + + av_strerror(Error::BsfNotFound.into(), STRINGS[Error::BsfNotFound.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::DecoderNotFound.into(), STRINGS[Error::DecoderNotFound.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::DemuxerNotFound.into(), STRINGS[Error::DemuxerNotFound.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::EncoderNotFound.into(), STRINGS[Error::EncoderNotFound.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::OptionNotFound.into(), STRINGS[Error::OptionNotFound.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::MuxerNotFound.into(), STRINGS[Error::MuxerNotFound.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::FilterNotFound.into(), STRINGS[Error::FilterNotFound.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::ProtocolNotFound.into(), STRINGS[Error::ProtocolNotFound.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::StreamNotFound.into(), STRINGS[Error::StreamNotFound.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + + av_strerror(Error::HttpBadRequest.into(), STRINGS[Error::HttpBadRequest.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::HttpUnauthorized.into(), STRINGS[Error::HttpUnauthorized.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::HttpForbidden.into(), STRINGS[Error::HttpForbidden.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::HttpNotFound.into(), STRINGS[Error::HttpNotFound.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::HttpOther4xx.into(), STRINGS[Error::HttpOther4xx.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + av_strerror(Error::HttpServerError.into(), STRINGS[Error::HttpServerError.index()].as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); + } +} + impl error::Error for Error { fn description(&self) -> &str { unsafe { - let mut desc = self.desc.borrow_mut(); - - if let None = *desc { - let mut buf = [0i8; AV_ERROR_MAX_STRING_SIZE as usize]; - av_strerror(self.code, buf.as_mut_ptr(), AV_ERROR_MAX_STRING_SIZE); - - *desc = Some(buf); - } - - from_utf8_unchecked(CStr::from_ptr(desc.unwrap().as_ptr()).to_bytes()) + from_utf8_unchecked(CStr::from_ptr(STRINGS[self.index()].as_ptr()).to_bytes()) } } }