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
use std::borrow::Cow;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use serde::{de::Deserializer, de::Error, ser::Serializer};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct MyBytesHelper<'a> {
    path: Cow<'a, Path>,
    bytes: Cow<'a, [u8]>,
}

#[derive(Clone, PartialEq, Debug)]
struct MyBytes {
    path: PathBuf,
    bytes: Vec<u8>,
}

impl MyBytes {
    pub fn open<P: AsRef<Path>>(p: P) -> io::Result<MyBytes> {
        println!("opening file in {}", std::process::id());
        let path = p.as_ref().to_path_buf();
        Ok(MyBytes {
            bytes: fs::read(&path)?,
            path,
        })
    }
}

impl Serialize for MyBytes {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        if procspawn::serde::in_ipc_mode() {
            println!("serialize in ipc mode");
            self.path.serialize(serializer)
        } else {
            println!("serialize in normal mode");
            MyBytesHelper {
                path: Cow::Borrowed(&self.path),
                bytes: Cow::Borrowed(&self.bytes),
            }
            .serialize(serializer)
        }
    }
}

impl<'de> Deserialize<'de> for MyBytes {
    fn deserialize<D>(deserializer: D) -> Result<MyBytes, D::Error>
    where
        D: Deserializer<'de>,
    {
        if procspawn::serde::in_ipc_mode() {
            println!("deserialize in ipc mode");
            let path = PathBuf::deserialize(deserializer)?;
            MyBytes::open(path).map_err(D::Error::custom)
        } else {
            println!("deserialize in normal mode");
            let helper = MyBytesHelper::deserialize(deserializer)?;
            Ok(MyBytes {
                path: helper.path.into_owned(),
                bytes: helper.bytes.into_owned(),
            })
        }
    }
}

fn main() {
    procspawn::init();

    let bytes = MyBytes::open("Cargo.toml").unwrap();

    let bytes_two = procspawn::spawn!((bytes.clone() => bytes) || {
        println!("length: {}", bytes.bytes.len());
        bytes
    })
    .join()
    .unwrap();

    assert_eq!(bytes, bytes_two);
}