slinky/
gp_info.rs

1/* SPDX-FileCopyrightText: © 2024 decompals */
2/* SPDX-License-Identifier: MIT */
3
4use serde::Deserialize;
5
6use crate::{absent_nullable::AbsentNullable, traits::Serial, Settings, SlinkyError};
7
8#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
9pub struct GpInfo {
10    // The relative section to emit the `_gp` symbol
11    pub section: String,
12    // An offset into the small data section, used to maximize the range of small data.
13    pub offset: i32,
14
15    /// Signals if the `_gp` symbol should be wrapped in a `PROVIDE` statement.
16    /// Can be used with `hidden`.
17    pub provide: bool,
18    /// Signals if the `_gp` symbol should be wrapped in a `HIDDEN` statement.
19    /// Can be used with `provide`.
20    pub hidden: bool,
21
22    pub include_if_any: Vec<(String, String)>,
23    pub include_if_all: Vec<(String, String)>,
24    pub exclude_if_any: Vec<(String, String)>,
25    pub exclude_if_all: Vec<(String, String)>,
26}
27
28fn gp_info_default_section() -> String {
29    ".sdata".to_string()
30}
31
32const fn gp_info_default_offset() -> i32 {
33    0x7FF0
34}
35
36const fn gp_info_default_provide() -> bool {
37    false
38}
39
40const fn gp_info_default_hidden() -> bool {
41    false
42}
43
44#[derive(Deserialize, PartialEq, Debug)]
45#[serde(deny_unknown_fields)]
46pub(crate) struct GpInfoSerial {
47    #[serde(default)]
48    pub section: AbsentNullable<String>,
49    #[serde(default)]
50    pub offset: AbsentNullable<i32>,
51
52    #[serde(default)]
53    pub provide: AbsentNullable<bool>,
54    #[serde(default)]
55    pub hidden: AbsentNullable<bool>,
56
57    #[serde(default)]
58    pub include_if_any: AbsentNullable<Vec<(String, String)>>,
59    #[serde(default)]
60    pub include_if_all: AbsentNullable<Vec<(String, String)>>,
61    #[serde(default)]
62    pub exclude_if_any: AbsentNullable<Vec<(String, String)>>,
63    #[serde(default)]
64    pub exclude_if_all: AbsentNullable<Vec<(String, String)>>,
65}
66
67impl Serial for GpInfoSerial {
68    type Output = GpInfo;
69
70    fn unserialize(self, _settings: &Settings) -> Result<Self::Output, SlinkyError> {
71        let section = {
72            let s = self
73                .section
74                .get_non_null("section", gp_info_default_section)?;
75            if s.is_empty() {
76                return Err(SlinkyError::EmptyValue {
77                    name: "section".to_string(),
78                });
79            }
80            s
81        };
82
83        let offset = self.offset.get_non_null("offset", gp_info_default_offset)?;
84
85        let provide = self
86            .provide
87            .get_non_null("provide", gp_info_default_provide)?;
88        let hidden = self.hidden.get_non_null("hidden", gp_info_default_hidden)?;
89
90        let include_if_any = self
91            .include_if_any
92            .get_non_null_not_empty("include_if_any", Vec::new)?;
93        let include_if_all = self
94            .include_if_all
95            .get_non_null_not_empty("include_if_all", Vec::new)?;
96        let exclude_if_any = self
97            .exclude_if_any
98            .get_non_null_not_empty("exclude_if_any", Vec::new)?;
99        let exclude_if_all = self
100            .exclude_if_all
101            .get_non_null_not_empty("exclude_if_all", Vec::new)?;
102
103        Ok(Self::Output {
104            section,
105            offset,
106            provide,
107            hidden,
108            include_if_any,
109            include_if_all,
110            exclude_if_any,
111            exclude_if_all,
112        })
113    }
114}