object_store/
tags.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
18use url::form_urlencoded::Serializer;
19
20/// A collection of key value pairs used to annotate objects
21///
22/// <https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-tagging.html>
23/// <https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags>
24#[derive(Debug, Clone, Default, Eq, PartialEq)]
25pub struct TagSet(String);
26
27impl TagSet {
28    /// Append a key value pair to this [`TagSet`]
29    ///
30    /// Stores have different restrictions on what characters are permitted,
31    /// for portability it is recommended applications use no more than 10 tags,
32    /// and stick to alphanumeric characters, and `+ - = . _ : /`
33    ///
34    /// <https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html>
35    /// <https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags?tabs=azure-ad#request-body>
36    pub fn push(&mut self, key: &str, value: &str) {
37        Serializer::new(&mut self.0).append_pair(key, value);
38    }
39
40    /// Return this [`TagSet`] as a URL-encoded string
41    pub fn encoded(&self) -> &str {
42        &self.0
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn test_tag_set() {
52        let mut set = TagSet::default();
53        set.push("test/foo", "value sdlks");
54        set.push("foo", " sdf _ /+./sd");
55        assert_eq!(
56            set.encoded(),
57            "test%2Ffoo=value+sdlks&foo=+sdf+_+%2F%2B.%2Fsd"
58        );
59    }
60}