pyo3/impl_/
introspection.rs1use crate::conversion::IntoPyObject;
2use crate::inspect::PyStaticExpr;
3
4mod return_type {
6 use crate::{impl_::introspection::PyReturnType, IntoPyObject};
7
8 pub trait Sealed {}
9
10 impl<'a, T: IntoPyObject<'a>> Sealed for T {}
11 impl<T: PyReturnType, E> Sealed for Result<T, E> {}
12}
13
14pub trait PyReturnType: return_type::Sealed {
18 const OUTPUT_TYPE: PyStaticExpr;
20}
21
22impl<'a, T: IntoPyObject<'a>> PyReturnType for T {
23 const OUTPUT_TYPE: PyStaticExpr = T::OUTPUT_TYPE;
24}
25
26impl<T: PyReturnType, E> PyReturnType for Result<T, E> {
27 const OUTPUT_TYPE: PyStaticExpr = T::OUTPUT_TYPE;
28}
29
30#[diagnostic::on_unimplemented(
31 message = "`{Self}` cannot be converted to a Python object",
32 label = "required by `#[pyo3(get)]` to create a readable property from a field of type `{Self}`",
33 note = "implement `IntoPyObject` for `&{Self}` or `IntoPyObject + Clone` for `{Self}` to define the conversion"
34)]
35pub trait PyIntoPyObjectMaybeRefType<const REF_IMPL_EXISTS: bool> {
36 const OUTPUT_TYPE: PyStaticExpr;
37}
38
39impl<'a, 'py, T: 'a> PyIntoPyObjectMaybeRefType<true> for T
40where
41 &'a T: IntoPyObject<'py>,
42{
43 const OUTPUT_TYPE: PyStaticExpr = <&T as IntoPyObject<'_>>::OUTPUT_TYPE;
44}
45
46impl<'py, T: IntoPyObject<'py>> PyIntoPyObjectMaybeRefType<false> for T {
47 const OUTPUT_TYPE: PyStaticExpr = <T as IntoPyObject<'_>>::OUTPUT_TYPE;
48}
49
50#[repr(C)]
51pub struct SerializedIntrospectionFragment<const LEN: usize> {
52 pub length: u32,
53 pub fragment: [u8; LEN],
54}
55
56pub const fn escape_json_string(input: &str, output: &mut [u8]) -> usize {
60 let input = input.as_bytes();
61 let mut input_i = 0;
62 let mut output_i = 0;
63 while input_i < input.len() {
64 match input[input_i] {
65 b'\\' => {
66 output[output_i] = b'\\';
67 output_i += 1;
68 output[output_i] = b'\\';
69 output_i += 1;
70 }
71 b'"' => {
72 output[output_i] = b'\\';
73 output_i += 1;
74 output[output_i] = b'"';
75 output_i += 1;
76 }
77 0x08 => {
78 output[output_i] = b'\\';
79 output_i += 1;
80 output[output_i] = b'b';
81 output_i += 1;
82 }
83 0x0C => {
84 output[output_i] = b'\\';
85 output_i += 1;
86 output[output_i] = b'f';
87 output_i += 1;
88 }
89 b'\n' => {
90 output[output_i] = b'\\';
91 output_i += 1;
92 output[output_i] = b'n';
93 output_i += 1;
94 }
95 b'\r' => {
96 output[output_i] = b'\\';
97 output_i += 1;
98 output[output_i] = b'r';
99 output_i += 1;
100 }
101 b'\t' => {
102 output[output_i] = b'\\';
103 output_i += 1;
104 output[output_i] = b't';
105 output_i += 1;
106 }
107 c @ 0..32 => {
108 output[output_i] = b'\\';
109 output_i += 1;
110 output[output_i] = b'u';
111 output_i += 1;
112 output[output_i] = b'0';
113 output_i += 1;
114 output[output_i] = b'0';
115 output_i += 1;
116 output[output_i] = b'0' + (c / 16);
117 output_i += 1;
118 let remainder = c % 16;
119 output[output_i] = if remainder >= 10 {
120 b'a' + remainder - 10
121 } else {
122 b'0' + remainder
123 };
124 output_i += 1;
125 }
126 c => {
127 output[output_i] = c;
128 output_i += 1;
129 }
130 }
131 input_i += 1;
132 }
133 output_i
134}
135
136pub const fn escaped_json_string_len(input: &str) -> usize {
138 let input = input.as_bytes();
139 let mut len = 0;
140 let mut i = 0;
141 while i < input.len() {
142 len += match input[i] {
143 b'\\' | b'"' | 0x08 | 0x0C | b'\n' | b'\r' | b'\t' => 2,
144 0..32 => 6,
145 _ => 1,
146 };
147 i += 1;
148 }
149 len
150}