1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use std::os::raw::c_char;
use std::path::Path;

use crate::internal_prelude::*;

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
pub struct StreamingGenerator(pub(crate) Handle);

impl StreamingGenerator {
    pub fn from_file<P: AsRef<Path>>(context: &Context, path: P) -> Result<StreamingGenerator> {
        let path = path.as_ref();
        let u_str = path
            .to_str()
            .ok_or_else(|| Error::rust_error("Path is not valid utf8"))?;
        let c_str = std::ffi::CString::new(u_str)
            .map_err(|_| Error::rust_error("Path contains a NULL byte"))?;

        wrap_constructor(|ud, cb| {
            let mut h = Default::default();
            check_error(unsafe {
                syz_createStreamingGeneratorFromFile(
                    &mut h,
                    context.to_syz_handle(),
                    c_str.as_ptr(),
                    null_mut(),
                    ud,
                    Some(cb),
                )
            })?;
            Ok(StreamingGenerator(Handle::new(h)))
        })
    }

    pub fn from_stream_handle(
        context: &Context,
        handle: StreamHandle,
    ) -> Result<StreamingGenerator> {
        handle.with_userdata(move |sh, ud, cb| {
            let mut out = 0;
            check_error(unsafe {
                syz_createStreamingGeneratorFromStreamHandle(
                    &mut out as *mut syz_Handle,
                    context.to_syz_handle(),
                    sh,
                    null_mut(),
                    ud,
                    Some(cb),
                )
            })?;
            let ret = StreamingGenerator(Handle::new(out));
            Ok(ret)
        })
    }

    pub fn from_stream_params(
        context: &Context,
        protocol: &str,
        path: &str,
        param: usize,
    ) -> Result<StreamingGenerator> {
        // The below transmute uses the fact that `usize` is the size of a
        // pointer on all common platforms.
        wrap_constructor(|ud, cb| {
            let mut h = Default::default();
            let protocol_c = std::ffi::CString::new(protocol)
                .map_err(|_| Error::rust_error("Unable to convert protocol to a C string"))?;
            let path_c = std::ffi::CString::new(path)
                .map_err(|_| Error::rust_error("Unable to convert path to a C string"))?;
            let protocol_ptr = protocol_c.as_ptr();
            let path_ptr = path_c.as_ptr();
            check_error(unsafe {
                syz_createStreamingGeneratorFromStreamParams(
                    &mut h as *mut syz_Handle,
                    context.to_syz_handle(),
                    protocol_ptr as *const c_char,
                    path_ptr as *const c_char,
                    std::mem::transmute(param),
                    null_mut(),
                    ud,
                    Some(cb),
                )
            })?;
            Ok(StreamingGenerator(Handle::new(h)))
        })
    }

    generator_properties!();
    bool_p!(SYZ_P_LOOPING, looping);
    double_p!(SYZ_P_PLAYBACK_POSITION, playback_position);

    object_common!();
    pausable_common!();
}

handle_traits!(StreamingGenerator);