opendal/services/ipfs/
ipld.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18/// Ref: <https://ipld.io/specs/codecs/dag-pb/spec/>
19#[derive(Clone, PartialEq, Eq, prost::Message)]
20pub struct PBNode {
21    #[prost(bytes = "vec", optional, tag = "1")]
22    pub data: Option<Vec<u8>>,
23    #[prost(message, repeated, tag = "2")]
24    pub links: Vec<PBLink>,
25}
26
27/// Ref: <https://ipld.io/specs/codecs/dag-pb/spec/>
28#[derive(Clone, PartialEq, Eq, prost::Message)]
29pub struct PBLink {
30    #[prost(bytes = "vec", optional, tag = "1")]
31    pub hash: Option<Vec<u8>>,
32    #[prost(string, optional, tag = "2")]
33    pub name: Option<String>,
34    #[prost(uint64, optional, tag = "3")]
35    pub tsize: Option<u64>,
36}
37
38/// This type is generated by [prost_build](https://docs.rs/prost-build/latest/prost_build/) via proto file `https://github.com/ipfs/go-unixfs/raw/master/pb/unixfs.proto`.
39//
40/// No modification has been and will be made from OpenDAL.
41#[derive(Clone, PartialEq, Eq, prost::Message)]
42pub struct Data {
43    #[prost(enumeration = "data::DataType", required, tag = "1")]
44    pub r#type: i32,
45    #[prost(bytes = "vec", optional, tag = "2")]
46    pub data: Option<Vec<u8>>,
47    #[prost(uint64, optional, tag = "3")]
48    pub filesize: Option<u64>,
49    #[prost(uint64, repeated, packed = "false", tag = "4")]
50    pub blocksizes: Vec<u64>,
51    #[prost(uint64, optional, tag = "5")]
52    pub hash_type: Option<u64>,
53    #[prost(uint64, optional, tag = "6")]
54    pub fanout: Option<u64>,
55}
56
57/// Nested message and enum types in `Data`.
58pub mod data {
59    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, prost::Enumeration)]
60    #[repr(i32)]
61    pub enum DataType {
62        Raw = 0,
63        Directory = 1,
64        File = 2,
65        Metadata = 3,
66        Symlink = 4,
67        HamtShard = 5,
68    }
69    impl DataType {
70        /// String value of the enum field names used in the ProtoBuf definition.
71        ///
72        /// The values are not transformed in any way and thus are considered stable
73        /// (if the ProtoBuf definition does not change) and safe for programmatic use.
74        pub fn as_str_name(&self) -> &'static str {
75            match self {
76                DataType::Raw => "Raw",
77                DataType::Directory => "Directory",
78                DataType::File => "File",
79                DataType::Metadata => "Metadata",
80                DataType::Symlink => "Symlink",
81                DataType::HamtShard => "HAMTShard",
82            }
83        }
84    }
85}
86
87#[derive(Clone, PartialEq, Eq, prost::Message)]
88pub struct Metadata {
89    #[prost(string, optional, tag = "1")]
90    pub mime_type: Option<String>,
91}
92
93#[cfg(test)]
94mod tests {
95    use bytes::Bytes;
96    use data::DataType;
97    use prost::Message;
98
99    use super::*;
100
101    /// Content is generated from `https://ipfs.io/ipfs/QmPpCt1aYGb9JWJRmXRUnmJtVgeFFTJGzWFYEEX7bo9zGJ`
102    /// with `accept: application/vnd.ipld.raw`
103    #[test]
104    fn test_message() {
105        let bs: Vec<u8> = vec![
106            0o022, 0o062, 0o012, 0o042, 0o022, 0o040, 0o220, 0o124, 0o225, 0o170, 0o152, 0o036,
107            0o040, 0o072, 0o032, 0o053, 0o143, 0o274, 0o044, 0o366, 0o215, 0o306, 0o177, 0o041,
108            0o260, 0o310, 0o231, 0o271, 0o142, 0o163, 0o006, 0o150, 0o054, 0o315, 0o227, 0o375,
109            0o347, 0o143, 0o022, 0o012, 0o156, 0o157, 0o162, 0o155, 0o141, 0o154, 0o137, 0o144,
110            0o151, 0o162, 0o030, 0o074, 0o022, 0o065, 0o012, 0o042, 0o022, 0o040, 0o337, 0o200,
111            0o021, 0o267, 0o364, 0o242, 0o030, 0o145, 0o257, 0o150, 0o205, 0o335, 0o100, 0o173,
112            0o222, 0o053, 0o074, 0o051, 0o041, 0o020, 0o203, 0o265, 0o116, 0o223, 0o111, 0o145,
113            0o040, 0o114, 0o350, 0o143, 0o354, 0o002, 0o022, 0o013, 0o156, 0o157, 0o162, 0o155,
114            0o141, 0o154, 0o137, 0o146, 0o151, 0o154, 0o145, 0o030, 0o216, 0o200, 0o020, 0o022,
115            0o064, 0o012, 0o042, 0o022, 0o040, 0o051, 0o305, 0o176, 0o211, 0o142, 0o044, 0o020,
116            0o267, 0o344, 0o172, 0o166, 0o374, 0o043, 0o010, 0o354, 0o047, 0o061, 0o031, 0o021,
117            0o121, 0o367, 0o014, 0o003, 0o002, 0o343, 0o032, 0o250, 0o353, 0o316, 0o263, 0o224,
118            0o142, 0o022, 0o012, 0o157, 0o156, 0o164, 0o151, 0o155, 0o145, 0o056, 0o143, 0o163,
119            0o166, 0o030, 0o215, 0o307, 0o005, 0o022, 0o067, 0o012, 0o042, 0o022, 0o040, 0o215,
120            0o225, 0o000, 0o035, 0o077, 0o302, 0o322, 0o271, 0o150, 0o077, 0o364, 0o202, 0o062,
121            0o144, 0o104, 0o074, 0o327, 0o111, 0o131, 0o233, 0o176, 0o144, 0o033, 0o076, 0o266,
122            0o144, 0o203, 0o256, 0o107, 0o257, 0o161, 0o112, 0o022, 0o016, 0o157, 0o156, 0o164,
123            0o151, 0o155, 0o145, 0o056, 0o143, 0o163, 0o166, 0o056, 0o142, 0o172, 0o062, 0o030,
124            0o206, 0o065, 0o022, 0o066, 0o012, 0o042, 0o022, 0o040, 0o205, 0o065, 0o360, 0o241,
125            0o222, 0o377, 0o267, 0o213, 0o334, 0o057, 0o060, 0o130, 0o230, 0o154, 0o213, 0o260,
126            0o123, 0o143, 0o011, 0o055, 0o365, 0o103, 0o002, 0o332, 0o213, 0o150, 0o275, 0o164,
127            0o162, 0o223, 0o350, 0o117, 0o022, 0o015, 0o157, 0o156, 0o164, 0o151, 0o155, 0o145,
128            0o056, 0o143, 0o163, 0o166, 0o056, 0o147, 0o172, 0o030, 0o217, 0o101, 0o022, 0o067,
129            0o012, 0o042, 0o022, 0o040, 0o202, 0o041, 0o276, 0o325, 0o105, 0o143, 0o237, 0o357,
130            0o121, 0o152, 0o300, 0o112, 0o067, 0o205, 0o022, 0o226, 0o021, 0o015, 0o302, 0o061,
131            0o135, 0o225, 0o320, 0o123, 0o030, 0o101, 0o007, 0o367, 0o157, 0o273, 0o154, 0o306,
132            0o022, 0o016, 0o157, 0o156, 0o164, 0o151, 0o155, 0o145, 0o056, 0o143, 0o163, 0o166,
133            0o056, 0o172, 0o163, 0o164, 0o030, 0o251, 0o103, 0o022, 0o111, 0o012, 0o042, 0o022,
134            0o040, 0o220, 0o124, 0o225, 0o170, 0o152, 0o036, 0o040, 0o072, 0o032, 0o053, 0o143,
135            0o274, 0o044, 0o366, 0o215, 0o306, 0o177, 0o041, 0o260, 0o310, 0o231, 0o271, 0o142,
136            0o163, 0o006, 0o150, 0o054, 0o315, 0o227, 0o375, 0o347, 0o143, 0o022, 0o041, 0o163,
137            0o160, 0o145, 0o143, 0o151, 0o141, 0o154, 0o137, 0o144, 0o151, 0o162, 0o040, 0o040,
138            0o041, 0o100, 0o043, 0o044, 0o045, 0o136, 0o046, 0o052, 0o050, 0o051, 0o137, 0o053,
139            0o055, 0o075, 0o073, 0o047, 0o076, 0o074, 0o054, 0o077, 0o030, 0o074, 0o022, 0o114,
140            0o012, 0o042, 0o022, 0o040, 0o337, 0o200, 0o021, 0o267, 0o364, 0o242, 0o030, 0o145,
141            0o257, 0o150, 0o205, 0o335, 0o100, 0o173, 0o222, 0o053, 0o074, 0o051, 0o041, 0o020,
142            0o203, 0o265, 0o116, 0o223, 0o111, 0o145, 0o040, 0o114, 0o350, 0o143, 0o354, 0o002,
143            0o022, 0o042, 0o163, 0o160, 0o145, 0o143, 0o151, 0o141, 0o154, 0o137, 0o146, 0o151,
144            0o154, 0o145, 0o040, 0o040, 0o041, 0o100, 0o043, 0o044, 0o045, 0o136, 0o046, 0o052,
145            0o050, 0o051, 0o137, 0o053, 0o055, 0o075, 0o073, 0o047, 0o076, 0o074, 0o054, 0o077,
146            0o030, 0o216, 0o200, 0o020, 0o012, 0o002, 0o010, 0o001,
147        ];
148
149        let data = PBNode::decode(Bytes::from(bs)).expect("decode must succeed");
150        if let Some(bs) = data.data.clone() {
151            let d = Data::decode(Bytes::from(bs)).expect("decode must succeed");
152            assert_eq!(d.r#type, DataType::Directory as i32);
153        }
154
155        assert_eq!(data.links.len(), 8);
156        assert_eq!(data.links[0].name.as_ref().unwrap(), "normal_dir");
157        assert_eq!(data.links[0].tsize.unwrap(), 60);
158
159        assert_eq!(data.links[1].name.as_ref().unwrap(), "normal_file");
160        assert_eq!(data.links[1].tsize.unwrap(), 262158);
161    }
162}