File size: 2,115 Bytes
69f2337
 
 
 
 
a08f988
69f2337
 
 
 
 
 
 
 
 
 
a08f988
69f2337
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a08f988
69f2337
a08f988
69f2337
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import base64
from datetime import datetime
from uuid import UUID

from app.api.messages.schemas import Message
from app.api.participants.schemas import Participant
from app.core.config import (
    ENCODING_ASCII,
    ENCODING_UTF8,
    MESSAGE_EXPECTED_PARTS,
    MESSAGE_PARSE_EMPTY_ERROR,
    MESSAGE_PARSE_INVALID_ERROR,
    MESSAGE_SEPARATOR,
    TABLE_PARTICIPANTS,
    TABLE_TOPICS,
)
from app.core.link import Link, TopicLink, ParticipantLink


class MessageLineParser:
    SEPARATOR = MESSAGE_SEPARATOR
    EXPECTED_PARTS = MESSAGE_EXPECTED_PARTS

    @staticmethod
    def _decode_content(encoded: str) -> str:
        return base64.b64decode(encoded.encode(ENCODING_ASCII)).decode(ENCODING_UTF8)

    @staticmethod
    def _encode_content(value: str) -> str:
        return base64.b64encode(value.encode(ENCODING_UTF8)).decode(ENCODING_ASCII)

    @classmethod
    def parse(cls, line: str) -> Message:
        raw = line.strip()
        if not raw:
            raise ValueError(MESSAGE_PARSE_EMPTY_ERROR)

        parts = raw.split(cls.SEPARATOR)
        if len(parts) != cls.EXPECTED_PARTS:
            raise ValueError(MESSAGE_PARSE_INVALID_ERROR)

        (
            message_id,
            topic_raw,
            order_in_topic,
            participant_raw,
            created_at_value,
            encoded_content,
        ) = parts

        return Message(
            id=UUID(message_id),
            topic_id=Link.from_raw(topic_raw),
            order_in_topic=int(order_in_topic),
            participant_id=Link.from_raw(participant_raw),
            created_at=datetime.fromisoformat(created_at_value),
            content=cls._decode_content(encoded_content),
        )

    @classmethod
    def serialize(cls, message: Message) -> str:
        return cls.SEPARATOR.join(
            [
                str(message.id),
                message.topic_id.as_path(),
                str(message.order_in_topic),
                message.participant_id.as_path(),
                message.created_at.isoformat(),
                cls._encode_content(message.content),
            ]
        )