xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/xdrlib.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""Implements (a subset of) Sun XDR -- eXternal Data Representation.
2*cda5da8dSAndroid Build Coastguard Worker
3*cda5da8dSAndroid Build Coastguard WorkerSee: RFC 1014
4*cda5da8dSAndroid Build Coastguard Worker
5*cda5da8dSAndroid Build Coastguard Worker"""
6*cda5da8dSAndroid Build Coastguard Worker
7*cda5da8dSAndroid Build Coastguard Workerimport struct
8*cda5da8dSAndroid Build Coastguard Workerfrom io import BytesIO
9*cda5da8dSAndroid Build Coastguard Workerfrom functools import wraps
10*cda5da8dSAndroid Build Coastguard Workerimport warnings
11*cda5da8dSAndroid Build Coastguard Worker
12*cda5da8dSAndroid Build Coastguard Workerwarnings._deprecated(__name__, remove=(3, 13))
13*cda5da8dSAndroid Build Coastguard Worker
14*cda5da8dSAndroid Build Coastguard Worker__all__ = ["Error", "Packer", "Unpacker", "ConversionError"]
15*cda5da8dSAndroid Build Coastguard Worker
16*cda5da8dSAndroid Build Coastguard Worker# exceptions
17*cda5da8dSAndroid Build Coastguard Workerclass Error(Exception):
18*cda5da8dSAndroid Build Coastguard Worker    """Exception class for this module. Use:
19*cda5da8dSAndroid Build Coastguard Worker
20*cda5da8dSAndroid Build Coastguard Worker    except xdrlib.Error as var:
21*cda5da8dSAndroid Build Coastguard Worker        # var has the Error instance for the exception
22*cda5da8dSAndroid Build Coastguard Worker
23*cda5da8dSAndroid Build Coastguard Worker    Public ivars:
24*cda5da8dSAndroid Build Coastguard Worker        msg -- contains the message
25*cda5da8dSAndroid Build Coastguard Worker
26*cda5da8dSAndroid Build Coastguard Worker    """
27*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, msg):
28*cda5da8dSAndroid Build Coastguard Worker        self.msg = msg
29*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
30*cda5da8dSAndroid Build Coastguard Worker        return repr(self.msg)
31*cda5da8dSAndroid Build Coastguard Worker    def __str__(self):
32*cda5da8dSAndroid Build Coastguard Worker        return str(self.msg)
33*cda5da8dSAndroid Build Coastguard Worker
34*cda5da8dSAndroid Build Coastguard Worker
35*cda5da8dSAndroid Build Coastguard Workerclass ConversionError(Error):
36*cda5da8dSAndroid Build Coastguard Worker    pass
37*cda5da8dSAndroid Build Coastguard Worker
38*cda5da8dSAndroid Build Coastguard Workerdef raise_conversion_error(function):
39*cda5da8dSAndroid Build Coastguard Worker    """ Wrap any raised struct.errors in a ConversionError. """
40*cda5da8dSAndroid Build Coastguard Worker
41*cda5da8dSAndroid Build Coastguard Worker    @wraps(function)
42*cda5da8dSAndroid Build Coastguard Worker    def result(self, value):
43*cda5da8dSAndroid Build Coastguard Worker        try:
44*cda5da8dSAndroid Build Coastguard Worker            return function(self, value)
45*cda5da8dSAndroid Build Coastguard Worker        except struct.error as e:
46*cda5da8dSAndroid Build Coastguard Worker            raise ConversionError(e.args[0]) from None
47*cda5da8dSAndroid Build Coastguard Worker    return result
48*cda5da8dSAndroid Build Coastguard Worker
49*cda5da8dSAndroid Build Coastguard Worker
50*cda5da8dSAndroid Build Coastguard Workerclass Packer:
51*cda5da8dSAndroid Build Coastguard Worker    """Pack various data representations into a buffer."""
52*cda5da8dSAndroid Build Coastguard Worker
53*cda5da8dSAndroid Build Coastguard Worker    def __init__(self):
54*cda5da8dSAndroid Build Coastguard Worker        self.reset()
55*cda5da8dSAndroid Build Coastguard Worker
56*cda5da8dSAndroid Build Coastguard Worker    def reset(self):
57*cda5da8dSAndroid Build Coastguard Worker        self.__buf = BytesIO()
58*cda5da8dSAndroid Build Coastguard Worker
59*cda5da8dSAndroid Build Coastguard Worker    def get_buffer(self):
60*cda5da8dSAndroid Build Coastguard Worker        return self.__buf.getvalue()
61*cda5da8dSAndroid Build Coastguard Worker    # backwards compatibility
62*cda5da8dSAndroid Build Coastguard Worker    get_buf = get_buffer
63*cda5da8dSAndroid Build Coastguard Worker
64*cda5da8dSAndroid Build Coastguard Worker    @raise_conversion_error
65*cda5da8dSAndroid Build Coastguard Worker    def pack_uint(self, x):
66*cda5da8dSAndroid Build Coastguard Worker        self.__buf.write(struct.pack('>L', x))
67*cda5da8dSAndroid Build Coastguard Worker
68*cda5da8dSAndroid Build Coastguard Worker    @raise_conversion_error
69*cda5da8dSAndroid Build Coastguard Worker    def pack_int(self, x):
70*cda5da8dSAndroid Build Coastguard Worker        self.__buf.write(struct.pack('>l', x))
71*cda5da8dSAndroid Build Coastguard Worker
72*cda5da8dSAndroid Build Coastguard Worker    pack_enum = pack_int
73*cda5da8dSAndroid Build Coastguard Worker
74*cda5da8dSAndroid Build Coastguard Worker    def pack_bool(self, x):
75*cda5da8dSAndroid Build Coastguard Worker        if x: self.__buf.write(b'\0\0\0\1')
76*cda5da8dSAndroid Build Coastguard Worker        else: self.__buf.write(b'\0\0\0\0')
77*cda5da8dSAndroid Build Coastguard Worker
78*cda5da8dSAndroid Build Coastguard Worker    def pack_uhyper(self, x):
79*cda5da8dSAndroid Build Coastguard Worker        try:
80*cda5da8dSAndroid Build Coastguard Worker            self.pack_uint(x>>32 & 0xffffffff)
81*cda5da8dSAndroid Build Coastguard Worker        except (TypeError, struct.error) as e:
82*cda5da8dSAndroid Build Coastguard Worker            raise ConversionError(e.args[0]) from None
83*cda5da8dSAndroid Build Coastguard Worker        try:
84*cda5da8dSAndroid Build Coastguard Worker            self.pack_uint(x & 0xffffffff)
85*cda5da8dSAndroid Build Coastguard Worker        except (TypeError, struct.error) as e:
86*cda5da8dSAndroid Build Coastguard Worker            raise ConversionError(e.args[0]) from None
87*cda5da8dSAndroid Build Coastguard Worker
88*cda5da8dSAndroid Build Coastguard Worker    pack_hyper = pack_uhyper
89*cda5da8dSAndroid Build Coastguard Worker
90*cda5da8dSAndroid Build Coastguard Worker    @raise_conversion_error
91*cda5da8dSAndroid Build Coastguard Worker    def pack_float(self, x):
92*cda5da8dSAndroid Build Coastguard Worker        self.__buf.write(struct.pack('>f', x))
93*cda5da8dSAndroid Build Coastguard Worker
94*cda5da8dSAndroid Build Coastguard Worker    @raise_conversion_error
95*cda5da8dSAndroid Build Coastguard Worker    def pack_double(self, x):
96*cda5da8dSAndroid Build Coastguard Worker        self.__buf.write(struct.pack('>d', x))
97*cda5da8dSAndroid Build Coastguard Worker
98*cda5da8dSAndroid Build Coastguard Worker    def pack_fstring(self, n, s):
99*cda5da8dSAndroid Build Coastguard Worker        if n < 0:
100*cda5da8dSAndroid Build Coastguard Worker            raise ValueError('fstring size must be nonnegative')
101*cda5da8dSAndroid Build Coastguard Worker        data = s[:n]
102*cda5da8dSAndroid Build Coastguard Worker        n = ((n+3)//4)*4
103*cda5da8dSAndroid Build Coastguard Worker        data = data + (n - len(data)) * b'\0'
104*cda5da8dSAndroid Build Coastguard Worker        self.__buf.write(data)
105*cda5da8dSAndroid Build Coastguard Worker
106*cda5da8dSAndroid Build Coastguard Worker    pack_fopaque = pack_fstring
107*cda5da8dSAndroid Build Coastguard Worker
108*cda5da8dSAndroid Build Coastguard Worker    def pack_string(self, s):
109*cda5da8dSAndroid Build Coastguard Worker        n = len(s)
110*cda5da8dSAndroid Build Coastguard Worker        self.pack_uint(n)
111*cda5da8dSAndroid Build Coastguard Worker        self.pack_fstring(n, s)
112*cda5da8dSAndroid Build Coastguard Worker
113*cda5da8dSAndroid Build Coastguard Worker    pack_opaque = pack_string
114*cda5da8dSAndroid Build Coastguard Worker    pack_bytes = pack_string
115*cda5da8dSAndroid Build Coastguard Worker
116*cda5da8dSAndroid Build Coastguard Worker    def pack_list(self, list, pack_item):
117*cda5da8dSAndroid Build Coastguard Worker        for item in list:
118*cda5da8dSAndroid Build Coastguard Worker            self.pack_uint(1)
119*cda5da8dSAndroid Build Coastguard Worker            pack_item(item)
120*cda5da8dSAndroid Build Coastguard Worker        self.pack_uint(0)
121*cda5da8dSAndroid Build Coastguard Worker
122*cda5da8dSAndroid Build Coastguard Worker    def pack_farray(self, n, list, pack_item):
123*cda5da8dSAndroid Build Coastguard Worker        if len(list) != n:
124*cda5da8dSAndroid Build Coastguard Worker            raise ValueError('wrong array size')
125*cda5da8dSAndroid Build Coastguard Worker        for item in list:
126*cda5da8dSAndroid Build Coastguard Worker            pack_item(item)
127*cda5da8dSAndroid Build Coastguard Worker
128*cda5da8dSAndroid Build Coastguard Worker    def pack_array(self, list, pack_item):
129*cda5da8dSAndroid Build Coastguard Worker        n = len(list)
130*cda5da8dSAndroid Build Coastguard Worker        self.pack_uint(n)
131*cda5da8dSAndroid Build Coastguard Worker        self.pack_farray(n, list, pack_item)
132*cda5da8dSAndroid Build Coastguard Worker
133*cda5da8dSAndroid Build Coastguard Worker
134*cda5da8dSAndroid Build Coastguard Worker
135*cda5da8dSAndroid Build Coastguard Workerclass Unpacker:
136*cda5da8dSAndroid Build Coastguard Worker    """Unpacks various data representations from the given buffer."""
137*cda5da8dSAndroid Build Coastguard Worker
138*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, data):
139*cda5da8dSAndroid Build Coastguard Worker        self.reset(data)
140*cda5da8dSAndroid Build Coastguard Worker
141*cda5da8dSAndroid Build Coastguard Worker    def reset(self, data):
142*cda5da8dSAndroid Build Coastguard Worker        self.__buf = data
143*cda5da8dSAndroid Build Coastguard Worker        self.__pos = 0
144*cda5da8dSAndroid Build Coastguard Worker
145*cda5da8dSAndroid Build Coastguard Worker    def get_position(self):
146*cda5da8dSAndroid Build Coastguard Worker        return self.__pos
147*cda5da8dSAndroid Build Coastguard Worker
148*cda5da8dSAndroid Build Coastguard Worker    def set_position(self, position):
149*cda5da8dSAndroid Build Coastguard Worker        self.__pos = position
150*cda5da8dSAndroid Build Coastguard Worker
151*cda5da8dSAndroid Build Coastguard Worker    def get_buffer(self):
152*cda5da8dSAndroid Build Coastguard Worker        return self.__buf
153*cda5da8dSAndroid Build Coastguard Worker
154*cda5da8dSAndroid Build Coastguard Worker    def done(self):
155*cda5da8dSAndroid Build Coastguard Worker        if self.__pos < len(self.__buf):
156*cda5da8dSAndroid Build Coastguard Worker            raise Error('unextracted data remains')
157*cda5da8dSAndroid Build Coastguard Worker
158*cda5da8dSAndroid Build Coastguard Worker    def unpack_uint(self):
159*cda5da8dSAndroid Build Coastguard Worker        i = self.__pos
160*cda5da8dSAndroid Build Coastguard Worker        self.__pos = j = i+4
161*cda5da8dSAndroid Build Coastguard Worker        data = self.__buf[i:j]
162*cda5da8dSAndroid Build Coastguard Worker        if len(data) < 4:
163*cda5da8dSAndroid Build Coastguard Worker            raise EOFError
164*cda5da8dSAndroid Build Coastguard Worker        return struct.unpack('>L', data)[0]
165*cda5da8dSAndroid Build Coastguard Worker
166*cda5da8dSAndroid Build Coastguard Worker    def unpack_int(self):
167*cda5da8dSAndroid Build Coastguard Worker        i = self.__pos
168*cda5da8dSAndroid Build Coastguard Worker        self.__pos = j = i+4
169*cda5da8dSAndroid Build Coastguard Worker        data = self.__buf[i:j]
170*cda5da8dSAndroid Build Coastguard Worker        if len(data) < 4:
171*cda5da8dSAndroid Build Coastguard Worker            raise EOFError
172*cda5da8dSAndroid Build Coastguard Worker        return struct.unpack('>l', data)[0]
173*cda5da8dSAndroid Build Coastguard Worker
174*cda5da8dSAndroid Build Coastguard Worker    unpack_enum = unpack_int
175*cda5da8dSAndroid Build Coastguard Worker
176*cda5da8dSAndroid Build Coastguard Worker    def unpack_bool(self):
177*cda5da8dSAndroid Build Coastguard Worker        return bool(self.unpack_int())
178*cda5da8dSAndroid Build Coastguard Worker
179*cda5da8dSAndroid Build Coastguard Worker    def unpack_uhyper(self):
180*cda5da8dSAndroid Build Coastguard Worker        hi = self.unpack_uint()
181*cda5da8dSAndroid Build Coastguard Worker        lo = self.unpack_uint()
182*cda5da8dSAndroid Build Coastguard Worker        return int(hi)<<32 | lo
183*cda5da8dSAndroid Build Coastguard Worker
184*cda5da8dSAndroid Build Coastguard Worker    def unpack_hyper(self):
185*cda5da8dSAndroid Build Coastguard Worker        x = self.unpack_uhyper()
186*cda5da8dSAndroid Build Coastguard Worker        if x >= 0x8000000000000000:
187*cda5da8dSAndroid Build Coastguard Worker            x = x - 0x10000000000000000
188*cda5da8dSAndroid Build Coastguard Worker        return x
189*cda5da8dSAndroid Build Coastguard Worker
190*cda5da8dSAndroid Build Coastguard Worker    def unpack_float(self):
191*cda5da8dSAndroid Build Coastguard Worker        i = self.__pos
192*cda5da8dSAndroid Build Coastguard Worker        self.__pos = j = i+4
193*cda5da8dSAndroid Build Coastguard Worker        data = self.__buf[i:j]
194*cda5da8dSAndroid Build Coastguard Worker        if len(data) < 4:
195*cda5da8dSAndroid Build Coastguard Worker            raise EOFError
196*cda5da8dSAndroid Build Coastguard Worker        return struct.unpack('>f', data)[0]
197*cda5da8dSAndroid Build Coastguard Worker
198*cda5da8dSAndroid Build Coastguard Worker    def unpack_double(self):
199*cda5da8dSAndroid Build Coastguard Worker        i = self.__pos
200*cda5da8dSAndroid Build Coastguard Worker        self.__pos = j = i+8
201*cda5da8dSAndroid Build Coastguard Worker        data = self.__buf[i:j]
202*cda5da8dSAndroid Build Coastguard Worker        if len(data) < 8:
203*cda5da8dSAndroid Build Coastguard Worker            raise EOFError
204*cda5da8dSAndroid Build Coastguard Worker        return struct.unpack('>d', data)[0]
205*cda5da8dSAndroid Build Coastguard Worker
206*cda5da8dSAndroid Build Coastguard Worker    def unpack_fstring(self, n):
207*cda5da8dSAndroid Build Coastguard Worker        if n < 0:
208*cda5da8dSAndroid Build Coastguard Worker            raise ValueError('fstring size must be nonnegative')
209*cda5da8dSAndroid Build Coastguard Worker        i = self.__pos
210*cda5da8dSAndroid Build Coastguard Worker        j = i + (n+3)//4*4
211*cda5da8dSAndroid Build Coastguard Worker        if j > len(self.__buf):
212*cda5da8dSAndroid Build Coastguard Worker            raise EOFError
213*cda5da8dSAndroid Build Coastguard Worker        self.__pos = j
214*cda5da8dSAndroid Build Coastguard Worker        return self.__buf[i:i+n]
215*cda5da8dSAndroid Build Coastguard Worker
216*cda5da8dSAndroid Build Coastguard Worker    unpack_fopaque = unpack_fstring
217*cda5da8dSAndroid Build Coastguard Worker
218*cda5da8dSAndroid Build Coastguard Worker    def unpack_string(self):
219*cda5da8dSAndroid Build Coastguard Worker        n = self.unpack_uint()
220*cda5da8dSAndroid Build Coastguard Worker        return self.unpack_fstring(n)
221*cda5da8dSAndroid Build Coastguard Worker
222*cda5da8dSAndroid Build Coastguard Worker    unpack_opaque = unpack_string
223*cda5da8dSAndroid Build Coastguard Worker    unpack_bytes = unpack_string
224*cda5da8dSAndroid Build Coastguard Worker
225*cda5da8dSAndroid Build Coastguard Worker    def unpack_list(self, unpack_item):
226*cda5da8dSAndroid Build Coastguard Worker        list = []
227*cda5da8dSAndroid Build Coastguard Worker        while 1:
228*cda5da8dSAndroid Build Coastguard Worker            x = self.unpack_uint()
229*cda5da8dSAndroid Build Coastguard Worker            if x == 0: break
230*cda5da8dSAndroid Build Coastguard Worker            if x != 1:
231*cda5da8dSAndroid Build Coastguard Worker                raise ConversionError('0 or 1 expected, got %r' % (x,))
232*cda5da8dSAndroid Build Coastguard Worker            item = unpack_item()
233*cda5da8dSAndroid Build Coastguard Worker            list.append(item)
234*cda5da8dSAndroid Build Coastguard Worker        return list
235*cda5da8dSAndroid Build Coastguard Worker
236*cda5da8dSAndroid Build Coastguard Worker    def unpack_farray(self, n, unpack_item):
237*cda5da8dSAndroid Build Coastguard Worker        list = []
238*cda5da8dSAndroid Build Coastguard Worker        for i in range(n):
239*cda5da8dSAndroid Build Coastguard Worker            list.append(unpack_item())
240*cda5da8dSAndroid Build Coastguard Worker        return list
241*cda5da8dSAndroid Build Coastguard Worker
242*cda5da8dSAndroid Build Coastguard Worker    def unpack_array(self, unpack_item):
243*cda5da8dSAndroid Build Coastguard Worker        n = self.unpack_uint()
244*cda5da8dSAndroid Build Coastguard Worker        return self.unpack_farray(n, unpack_item)
245