libktx_rs/
sinks.rs

1// Copyright (C) 2021 Paolo Jovon <paolo.jovon@gmail.com>
2// SPDX-License-Identifier: Apache-2.0
3#![cfg(feature = "write")]
4
5//! [`crate::texture::TextureSink`] implementations for writing [`Texture`]s out to.
6
7use crate::{
8    enums::ktx_result,
9    stream::{RWSeekable, RustKtxStream},
10    texture::{Texture, TextureSink},
11    KtxError,
12};
13use std::sync::{Arc, Mutex};
14
15/// A [`TextureSink`] that writes to a [`RustKtxStream`].
16#[derive(Debug)]
17pub struct StreamSink<'a, T: RWSeekable + ?Sized + 'a> {
18    stream: Arc<Mutex<RustKtxStream<'a, T>>>,
19}
20
21impl<'a, T: RWSeekable + ?Sized + 'a> StreamSink<'a, T> {
22    /// Creates a new stream sink that will write to the given `inner` stream.
23    pub fn new(inner: Arc<Mutex<RustKtxStream<'a, T>>>) -> Self {
24        StreamSink { stream: inner }
25    }
26
27    /// Destroys this stream sink, giving back the underlying `inner` stream.
28    pub fn into_inner(self) -> Arc<Mutex<RustKtxStream<'a, T>>> {
29        self.stream
30    }
31}
32
33impl<'a, T: RWSeekable + ?Sized + 'a> TextureSink for StreamSink<'a, T> {
34    fn write_texture(&mut self, texture: &Texture) -> Result<(), KtxError> {
35        // SAFETY: Safe if `texture.handle` is sound.
36        let vtbl = unsafe { (*texture.handle).vtbl };
37        let write_pfn = match unsafe { (*vtbl).WriteToStream } {
38            Some(pfn) => pfn,
39            None => return Err(KtxError::InvalidValue),
40        };
41        let err = unsafe {
42            write_pfn(
43                texture.handle,
44                self.stream
45                    .lock()
46                    .expect("Poisoned self.stream lock")
47                    .ktx_stream(),
48            )
49        };
50        ktx_result(err, ())
51    }
52}