xref: /aosp_15_r20/external/pigweed/pw_tokenizer/py/pw_tokenizer/serial_detokenizer.py (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1#!/usr/bin/env python3
2# Copyright 2020 The Pigweed Authors
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may not
5# use this file except in compliance with the License. You may obtain a copy of
6# the License at
7#
8#     https://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations under
14# the License.
15"""Decodes and detokenizes Base64-encoded strings in serial output.
16
17The output is printed or saved to a file. Input is not supported.
18"""
19
20import argparse
21import sys
22from typing import BinaryIO, Iterable
23
24import serial
25from pw_tokenizer import database, detokenize, encode, tokens
26
27
28def _parse_args():
29    """Parses and return command line arguments."""
30
31    parser = argparse.ArgumentParser(
32        description=__doc__,
33        formatter_class=argparse.RawDescriptionHelpFormatter,
34        parents=[database.token_databases_parser()],
35    )
36    parser.add_argument(
37        '-d',
38        '--device',
39        required=True,
40        help='The serial device from which to read',
41    )
42    parser.add_argument(
43        '-b',
44        '--baudrate',
45        type=int,
46        default=115200,
47        help='The baud rate for the serial device',
48    )
49    parser.add_argument(
50        '-o',
51        '--output',
52        type=argparse.FileType('wb'),
53        default=sys.stdout.buffer,
54        help=(
55            'The file to which to write the output; '
56            'provide - or omit for stdout.'
57        ),
58    )
59    parser.add_argument(
60        '-p',
61        '--prefix',
62        default=encode.NESTED_TOKEN_PREFIX,
63        help=(
64            'The one-character prefix that signals the start of a '
65            'Base64-encoded message. (default: $)'
66        ),
67    )
68    parser.add_argument(
69        '-s',
70        '--show_errors',
71        action='store_true',
72        help=(
73            'Show error messages instead of conversion specifiers when '
74            'arguments cannot be decoded.'
75        ),
76    )
77
78    return parser.parse_args()
79
80
81def _detokenize_serial(
82    databases: Iterable,
83    device: str,
84    baudrate: int,
85    show_errors: bool,
86    output: BinaryIO,
87    prefix: str,
88) -> None:
89    if output is sys.stdout:
90        output = sys.stdout.buffer
91
92    detokenizer = detokenize.Detokenizer(
93        tokens.Database.merged(*databases),
94        prefix=prefix,
95        show_errors=show_errors,
96    )
97    serial_device = serial.Serial(port=device, baudrate=baudrate)
98
99    try:
100        detokenizer.detokenize_base64_live(serial_device, output)
101    except KeyboardInterrupt:
102        output.flush()
103
104
105def main():
106    _detokenize_serial(**vars(_parse_args()))
107    return 0
108
109
110if __name__ == '__main__':
111    sys.exit(main())
112