Struct apple_codesign::dmg::KolyTrailer
source · pub struct KolyTrailer {Show 26 fields
pub signature: [u8; 4],
pub version: u32,
pub header_size: u32,
pub flags: u32,
pub running_data_fork_offset: u64,
pub data_fork_offset: u64,
pub data_fork_length: u64,
pub rsrc_fork_offset: u64,
pub rsrc_fork_length: u64,
pub segment_number: u32,
pub segment_count: u32,
pub segment_id: [u32; 4],
pub data_fork_digest_type: u32,
pub data_fork_digest_size: u32,
pub data_fork_digest: [u32; 32],
pub plist_offset: u64,
pub plist_length: u64,
pub reserved1: [u64; 8],
pub code_signature_offset: u64,
pub code_signature_size: u64,
pub reserved2: [u64; 5],
pub main_digest_type: u32,
pub main_digest_size: u32,
pub main_digest: [u32; 32],
pub image_variant: u32,
pub sector_count: u64,
}Expand description
DMG trailer describing file content.
This is the main structure defining a DMG.
Fields§
§signature: [u8; 4]“koly”
version: u32§header_size: u32§flags: u32§running_data_fork_offset: u64§data_fork_offset: u64§data_fork_length: u64§rsrc_fork_offset: u64§rsrc_fork_length: u64§segment_number: u32§segment_count: u32§segment_id: [u32; 4]§data_fork_digest_type: u32§data_fork_digest_size: u32§data_fork_digest: [u32; 32]§plist_offset: u64§plist_length: u64§reserved1: [u64; 8]§code_signature_offset: u64§code_signature_size: u64§reserved2: [u64; 5]§main_digest_type: u32§main_digest_size: u32§main_digest: [u32; 32]§image_variant: u32§sector_count: u64Implementations§
source§impl KolyTrailer
impl KolyTrailer
sourcepub fn read_from<R: Read + Seek>(
reader: &mut R
) -> Result<Self, AppleCodesignError>
pub fn read_from<R: Read + Seek>(
reader: &mut R
) -> Result<Self, AppleCodesignError>
Construct an instance by reading from a seekable reader.
The trailer is the final 512 bytes of the seekable stream.
Examples found in repository?
src/dmg.rs (line 161)
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
pub fn new<R: Read + Seek>(reader: &mut R) -> Result<Self, AppleCodesignError> {
let koly = KolyTrailer::read_from(reader)?;
let code_signature_offset = koly.code_signature_offset;
let code_signature_size = koly.code_signature_size;
let code_signature_data = if code_signature_offset != 0 && code_signature_size != 0 {
reader.seek(SeekFrom::Start(code_signature_offset))?;
let mut data = vec![];
reader.take(code_signature_size).read_to_end(&mut data)?;
Some(data)
} else {
None
};
Ok(Self {
koly,
code_signature_data,
})
}
/// Obtain the main data structure describing this DMG.
pub fn koly(&self) -> &KolyTrailer {
&self.koly
}
/// Obtain the embedded code signature superblob.
pub fn embedded_signature(&self) -> Result<Option<EmbeddedSignature<'_>>, AppleCodesignError> {
if let Some(data) = &self.code_signature_data {
Ok(Some(EmbeddedSignature::from_bytes(data)?))
} else {
Ok(None)
}
}
/// Digest an arbitrary slice of the file.
fn digest_slice_with<R: Read + Seek>(
&self,
digest: DigestType,
reader: &mut R,
offset: u64,
length: u64,
) -> Result<Digest<'static>, AppleCodesignError> {
reader.seek(SeekFrom::Start(offset))?;
let mut reader = reader.take(length);
let mut d = digest.as_hasher()?;
loop {
let mut buffer = [0u8; 16384];
let count = reader.read(&mut buffer)?;
d.update(&buffer[0..count]);
if count == 0 {
break;
}
}
Ok(Digest {
data: d.finish().as_ref().to_vec().into(),
})
}
/// Digest the content of the DMG up to the code signature or [KolyTrailer].
///
/// This digest is used as the code digest in the code directory.
pub fn digest_content_with<R: Read + Seek>(
&self,
digest: DigestType,
reader: &mut R,
) -> Result<Digest<'static>, AppleCodesignError> {
if self.koly.code_signature_offset != 0 {
self.digest_slice_with(digest, reader, 0, self.koly.code_signature_offset)
} else {
reader.seek(SeekFrom::End(-KOLY_SIZE))?;
let size = reader.stream_position()?;
self.digest_slice_with(digest, reader, 0, size)
}
}
}
/// Determines whether a filesystem path is a DMG.
///
/// Returns true if the path has a DMG trailer.
pub fn path_is_dmg(path: impl AsRef<Path>) -> Result<bool, AppleCodesignError> {
let mut fh = File::open(path.as_ref())?;
Ok(KolyTrailer::read_from(&mut fh).is_ok())
}sourcepub fn offset_after_plist(&self) -> u64
pub fn offset_after_plist(&self) -> u64
Obtain the offset byte after the plist data.
This is the offset at which an embedded signature superblob would be present. If no embedded signature is present, this is likely the start of KolyTrailer.
Examples found in repository?
src/dmg.rs (line 139)
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
pub fn digest_for_code_directory(
&self,
digest: DigestType,
) -> Result<Vec<u8>, AppleCodesignError> {
let mut koly = self.clone();
koly.code_signature_size = 0;
koly.code_signature_offset = self.offset_after_plist();
let mut buf = [0u8; KOLY_SIZE as usize];
buf.pwrite_with(koly, 0, scroll::BE)?;
digest.digest_data(&buf)
}
}
/// An entity for reading DMG files.
///
/// It only implements enough to create code signatures over the DMG.
pub struct DmgReader {
koly: KolyTrailer,
/// Caches the embedded code signature data.
code_signature_data: Option<Vec<u8>>,
}
impl DmgReader {
/// Construct a new instance from a reader.
pub fn new<R: Read + Seek>(reader: &mut R) -> Result<Self, AppleCodesignError> {
let koly = KolyTrailer::read_from(reader)?;
let code_signature_offset = koly.code_signature_offset;
let code_signature_size = koly.code_signature_size;
let code_signature_data = if code_signature_offset != 0 && code_signature_size != 0 {
reader.seek(SeekFrom::Start(code_signature_offset))?;
let mut data = vec![];
reader.take(code_signature_size).read_to_end(&mut data)?;
Some(data)
} else {
None
};
Ok(Self {
koly,
code_signature_data,
})
}
/// Obtain the main data structure describing this DMG.
pub fn koly(&self) -> &KolyTrailer {
&self.koly
}
/// Obtain the embedded code signature superblob.
pub fn embedded_signature(&self) -> Result<Option<EmbeddedSignature<'_>>, AppleCodesignError> {
if let Some(data) = &self.code_signature_data {
Ok(Some(EmbeddedSignature::from_bytes(data)?))
} else {
Ok(None)
}
}
/// Digest an arbitrary slice of the file.
fn digest_slice_with<R: Read + Seek>(
&self,
digest: DigestType,
reader: &mut R,
offset: u64,
length: u64,
) -> Result<Digest<'static>, AppleCodesignError> {
reader.seek(SeekFrom::Start(offset))?;
let mut reader = reader.take(length);
let mut d = digest.as_hasher()?;
loop {
let mut buffer = [0u8; 16384];
let count = reader.read(&mut buffer)?;
d.update(&buffer[0..count]);
if count == 0 {
break;
}
}
Ok(Digest {
data: d.finish().as_ref().to_vec().into(),
})
}
/// Digest the content of the DMG up to the code signature or [KolyTrailer].
///
/// This digest is used as the code digest in the code directory.
pub fn digest_content_with<R: Read + Seek>(
&self,
digest: DigestType,
reader: &mut R,
) -> Result<Digest<'static>, AppleCodesignError> {
if self.koly.code_signature_offset != 0 {
self.digest_slice_with(digest, reader, 0, self.koly.code_signature_offset)
} else {
reader.seek(SeekFrom::End(-KOLY_SIZE))?;
let size = reader.stream_position()?;
self.digest_slice_with(digest, reader, 0, size)
}
}
}
/// Determines whether a filesystem path is a DMG.
///
/// Returns true if the path has a DMG trailer.
pub fn path_is_dmg(path: impl AsRef<Path>) -> Result<bool, AppleCodesignError> {
let mut fh = File::open(path.as_ref())?;
Ok(KolyTrailer::read_from(&mut fh).is_ok())
}
/// Entity for signing DMG files.
#[derive(Clone, Debug, Default)]
pub struct DmgSigner {}
impl DmgSigner {
/// Sign a DMG.
///
/// Parameters controlling the signing operation are specified by `settings`.
///
/// `file` is a readable and writable file. The DMG signature will be written
/// into the source file.
pub fn sign_file(
&self,
settings: &SigningSettings,
fh: &mut File,
) -> Result<(), AppleCodesignError> {
warn!("signing DMG");
let koly = DmgReader::new(fh)?.koly().clone();
let signature = self.create_superblob(settings, fh)?;
Self::write_embedded_signature(fh, koly, &signature)
}
/// Staple a notarization ticket to a DMG.
pub fn staple_file(
&self,
fh: &mut File,
ticket_data: Vec<u8>,
) -> Result<(), AppleCodesignError> {
warn!(
"stapling DMG with {} byte notarization ticket",
ticket_data.len()
);
let reader = DmgReader::new(fh)?;
let koly = reader.koly().clone();
let signature = reader
.embedded_signature()?
.ok_or(AppleCodesignError::DmgStapleNoSignature)?;
let mut builder = EmbeddedSignatureBuilder::new_for_stapling(signature)?;
builder.add_notarization_ticket(ticket_data)?;
let signature = builder.create_superblob()?;
Self::write_embedded_signature(fh, koly, &signature)
}
fn write_embedded_signature(
fh: &mut File,
mut koly: KolyTrailer,
signature: &[u8],
) -> Result<(), AppleCodesignError> {
warn!("writing {} byte signature", signature.len());
fh.seek(SeekFrom::Start(koly.offset_after_plist()))?;
fh.write_all(signature)?;
koly.code_signature_offset = koly.offset_after_plist();
koly.code_signature_size = signature.len() as _;
let mut trailer = [0u8; KOLY_SIZE as usize];
trailer.pwrite_with(&koly, 0, scroll::BE)?;
fh.write_all(&trailer)?;
fh.set_len(koly.code_signature_offset + koly.code_signature_size + KOLY_SIZE as u64)?;
Ok(())
}
/// Create the embedded signature superblob content.
pub fn create_superblob<F: Read + Write + Seek>(
&self,
settings: &SigningSettings,
fh: &mut F,
) -> Result<Vec<u8>, AppleCodesignError> {
let mut builder = EmbeddedSignatureBuilder::default();
for (slot, blob) in self.create_special_blobs()? {
builder.add_blob(slot, blob)?;
}
builder.add_code_directory(
CodeSigningSlot::CodeDirectory,
self.create_code_directory(settings, fh)?,
)?;
if let Some((signing_key, signing_cert)) = settings.signing_key() {
builder.create_cms_signature(
signing_key,
signing_cert,
settings.time_stamp_url(),
settings.certificate_chain().iter().cloned(),
)?;
}
builder.create_superblob()
}
/// Create the code directory data structure that is part of the embedded signature.
///
/// This won't be the final data structure state that is serialized, as it may be
/// amended to in other functions.
pub fn create_code_directory<F: Read + Write + Seek>(
&self,
settings: &SigningSettings,
fh: &mut F,
) -> Result<CodeDirectoryBlob<'static>, AppleCodesignError> {
let reader = DmgReader::new(fh)?;
let mut flags = settings
.code_signature_flags(SettingsScope::Main)
.unwrap_or_else(CodeSignatureFlags::empty);
if settings.signing_key().is_some() {
flags -= CodeSignatureFlags::ADHOC;
} else {
flags |= CodeSignatureFlags::ADHOC;
}
warn!("using code signature flags: {:?}", flags);
let ident = Cow::Owned(
settings
.binary_identifier(SettingsScope::Main)
.ok_or(AppleCodesignError::NoIdentifier)?
.to_string(),
);
warn!("using identifier {}", ident);
let code_hashes = vec![reader.digest_content_with(*settings.digest_type(), fh)?];
let koly_digest = reader
.koly()
.digest_for_code_directory(*settings.digest_type())?;
let mut cd = CodeDirectoryBlob {
version: 0x20100,
flags,
code_limit: reader.koly().offset_after_plist() as u32,
digest_size: settings.digest_type().hash_len()? as u8,
digest_type: *settings.digest_type(),
page_size: 1,
ident,
code_digests: code_hashes,
..Default::default()
};
cd.set_slot_digest(CodeSigningSlot::RepSpecific, koly_digest)?;
Ok(cd)
}sourcepub fn digest_for_code_directory(
&self,
digest: DigestType
) -> Result<Vec<u8>, AppleCodesignError>
pub fn digest_for_code_directory(
&self,
digest: DigestType
) -> Result<Vec<u8>, AppleCodesignError>
Obtain the digest of the trailer in a way compatible with code directory digesting.
This will compute the digest of the current values but with the code signature size set to 0.
Examples found in repository?
src/dmg.rs (line 390)
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
pub fn create_code_directory<F: Read + Write + Seek>(
&self,
settings: &SigningSettings,
fh: &mut F,
) -> Result<CodeDirectoryBlob<'static>, AppleCodesignError> {
let reader = DmgReader::new(fh)?;
let mut flags = settings
.code_signature_flags(SettingsScope::Main)
.unwrap_or_else(CodeSignatureFlags::empty);
if settings.signing_key().is_some() {
flags -= CodeSignatureFlags::ADHOC;
} else {
flags |= CodeSignatureFlags::ADHOC;
}
warn!("using code signature flags: {:?}", flags);
let ident = Cow::Owned(
settings
.binary_identifier(SettingsScope::Main)
.ok_or(AppleCodesignError::NoIdentifier)?
.to_string(),
);
warn!("using identifier {}", ident);
let code_hashes = vec![reader.digest_content_with(*settings.digest_type(), fh)?];
let koly_digest = reader
.koly()
.digest_for_code_directory(*settings.digest_type())?;
let mut cd = CodeDirectoryBlob {
version: 0x20100,
flags,
code_limit: reader.koly().offset_after_plist() as u32,
digest_size: settings.digest_type().hash_len()? as u8,
digest_type: *settings.digest_type(),
page_size: 1,
ident,
code_digests: code_hashes,
..Default::default()
};
cd.set_slot_digest(CodeSigningSlot::RepSpecific, koly_digest)?;
Ok(cd)
}Trait Implementations§
source§impl Clone for KolyTrailer
impl Clone for KolyTrailer
source§fn clone(&self) -> KolyTrailer
fn clone(&self) -> KolyTrailer
Returns a copy of the value. Read more
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moresource§impl Debug for KolyTrailer
impl Debug for KolyTrailer
source§impl PartialEq<KolyTrailer> for KolyTrailer
impl PartialEq<KolyTrailer> for KolyTrailer
source§fn eq(&self, other: &KolyTrailer) -> bool
fn eq(&self, other: &KolyTrailer) -> bool
This method tests for
self and other values to be equal, and is used
by ==.source§impl<'a> TryFromCtx<'a, Endian, [u8]> for KolyTrailerwhere
KolyTrailer: 'a,
impl<'a> TryFromCtx<'a, Endian, [u8]> for KolyTrailerwhere
KolyTrailer: 'a,
source§impl<'a> TryIntoCtx<Endian, [u8]> for &'a KolyTrailer
impl<'a> TryIntoCtx<Endian, [u8]> for &'a KolyTrailer
source§impl TryIntoCtx<Endian, [u8]> for KolyTrailer
impl TryIntoCtx<Endian, [u8]> for KolyTrailer
impl Eq for KolyTrailer
impl StructuralEq for KolyTrailer
impl StructuralPartialEq for KolyTrailer
Auto Trait Implementations§
impl RefUnwindSafe for KolyTrailer
impl Send for KolyTrailer
impl Sync for KolyTrailer
impl Unpin for KolyTrailer
impl UnwindSafe for KolyTrailer
Blanket Implementations§
§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
§impl<T> Conv for T
impl<T> Conv for T
source§impl<Q, K> Equivalent<K> for Qwhere
Q: Eq + ?Sized,
K: Borrow<Q> + ?Sized,
impl<Q, K> Equivalent<K> for Qwhere
Q: Eq + ?Sized,
K: Borrow<Q> + ?Sized,
source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
Compare self to
key and return true if they are equal.§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
Causes
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
Causes
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
Causes
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
Causes
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
Causes
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
Causes
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
Causes
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
Causes
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
Formats each item in a sequence. Read more
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Pipes by value. This is generally the method you want to use. Read more
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
Borrows
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
Mutably borrows
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> Rwhere
Self: Borrow<B>,
B: 'a + ?Sized,
R: 'a,
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> Rwhere
Self: Borrow<B>,
B: 'a + ?Sized,
R: 'a,
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R
) -> Rwhere
Self: BorrowMut<B>,
B: 'a + ?Sized,
R: 'a,
fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R
) -> Rwhere
Self: BorrowMut<B>,
B: 'a + ?Sized,
R: 'a,
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> Rwhere
Self: AsRef<U>,
U: 'a + ?Sized,
R: 'a,
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> Rwhere
Self: AsRef<U>,
U: 'a + ?Sized,
R: 'a,
Borrows
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> Rwhere
Self: AsMut<U>,
U: 'a + ?Sized,
R: 'a,
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> Rwhere
Self: AsMut<U>,
U: 'a + ?Sized,
R: 'a,
Mutably borrows
self, then passes self.as_mut() into the pipe
function.§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
Immutable access to the
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
Mutable access to the
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
Immutable access to the
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
Mutable access to the
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Selfwhere
Self: Deref<Target = T>,
T: ?Sized,
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Selfwhere
Self: Deref<Target = T>,
T: ?Sized,
Immutable access to the
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Selfwhere
Self: DerefMut<Target = T> + Deref,
T: ?Sized,
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Selfwhere
Self: DerefMut<Target = T> + Deref,
T: ?Sized,
Mutable access to the
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
Calls
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
Calls
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
Calls
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
Calls
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
Calls
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
Calls
.tap_ref_mut() only in debug builds, and is erased in release
builds.