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
96
//! Subplot data files
//!
//! Subplot can embed data files into test suites.  This module provides
//! the representation of the files in a way designed to be cheap to clone
//! so that they can be passed around "by value".

use std::path::{Path, PathBuf};
use std::sync::Arc;

use base64::decode;
/// An embedded data file.
///
/// Embedded data files have names and content.  The subplot template will generate
/// a `lazy_static` containing all the data files embedded into the suite.  Then
/// generated test functions will extract data files
///
/// If you are using them in your test steps you should take them by value:
///
/// ```rust
/// # use subplotlib::prelude::*;
/// # #[derive(Default)]
/// # struct Context {}
/// # impl ContextElement for Context {}
/// #[step]
/// fn step_using_a_file(context: &mut Context, somefile: SubplotDataFile) {
///     // context.stash_file(somefile);
/// }
///
/// # fn main() {}
/// ```
///
/// For the generated test to correctly recognise how to pass a file in, you
/// **must** mark the argument as a file in your binding:
///
/// ```yaml
/// - when: using {somefile} as a input
///   function: step_using_a_file
///   types:
///     somefile: file
/// ```
#[derive(Debug)]
pub struct SubplotDataFile {
    name: Arc<Path>,
    data: Arc<[u8]>,
}

impl Clone for SubplotDataFile {
    fn clone(&self) -> Self {
        Self {
            name: Arc::clone(&self.name),
            data: Arc::clone(&self.data),
        }
    }
}

impl Default for SubplotDataFile {
    fn default() -> Self {
        Self {
            name: PathBuf::from("").into(),
            data: Vec::new().into(),
        }
    }
}

impl SubplotDataFile {
    /// Construct a new data file object
    ///
    /// Typically this will only be called from the generated test suite.
    /// The passed in name and data must be base64 encoded strings and each will
    /// be interpreted independently.  The name will be treated as a [`PathBuf`]
    /// and the data will be stored as a slice of bytes.
    ///
    /// Neither will be interpreted as utf8.
    ///
    /// # Panics
    ///
    /// This will panic if the passed in strings are not correctly base64 encoded.
    pub fn new(name: &str, data: &str) -> Self {
        let name = decode(name).expect("Subplot generated bad base64?");
        let name = String::from_utf8_lossy(&name);
        let name: PathBuf = name.as_ref().into();
        let name = name.into();
        let data = decode(data).expect("Subplot generated bad base64?").into();
        Self { name, data }
    }

    /// Retrieve the filename
    pub fn name(&self) -> &Path {
        &self.name
    }

    /// Retrieve the data
    pub fn data(&self) -> &[u8] {
        &self.data
    }
}