Coverage for src / renaissance / common / rewriter.py: 72%
39 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-09-09 14:04 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-09-09 14:04 +0000
1import sys
4class Rewrite:
5 def __init__(self, start: int, end: int, replacement: bytes) -> None:
6 self.start = start
7 self.end = end
8 self.replacement = replacement
11class Rewriter:
12 """A class that allows for modifications to a byte sequence."""
14 def __init__(self, content: bytes) -> None:
15 self.__content = content
16 self.__rewrites: list[Rewrite] = []
18 def replace(self, start: int, end: int, new_content: bytes) -> None:
19 """Replaces a portion of the content with new content.
21 This method will replace the content between the specified start and end
22 indices with the provided new_content. If there is an existing rewrite
23 that partially overlaps with the specified range, the new content will be
24 appended to the existing replacement, and the range will be adjusted to
25 encompass both the old and new content. If the start or end indices are out
26 of bounds, then new content will be inserted at the end of the byte sequence.
28 Args:
29 start (int): The starting index of the content to be replaced.
30 end (int): The ending index of the content to be replaced.
31 new_content (bytes): The new content to insert in place of the old content.
33 Returns:
34 None
36 """
37 for r in self.__rewrites:
38 # if r partially overlaps with start and end then append the new content to the existing replacement
39 if r.start <= start <= r.end:
40 r.replacement += new_content
41 r.start = min(r.start, start)
42 r.end = max(r.end, end)
43 return
44 real_start = len(self.__content) if start > len(self.__content) or start < 0 else start
45 real_end = len(self.__content) if end > len(self.__content) or end < 0 else end
46 self.__rewrites.append(Rewrite(real_start, real_end, new_content))
48 def apply(self) -> bytes:
49 """Applies the rewrites to a copied byte sequence.
51 This method reverses the order of the rewrites to ensure that insertions
52 are performed correctly. It then sorts the rewrites by their start position
53 in descending order and applies each rewrite to the byte sequence.
55 Returns:
56 bytes: The modified byte sequence after all rewrites have been applied.
58 """
59 result = bytearray(self.__content[:])
60 for rewrite in sorted(self.__rewrites, key=lambda x: x.start, reverse=True):
61 result[rewrite.start : rewrite.end] = rewrite.replacement
62 return result
64 @property
65 def content(self) -> bytes:
66 return self.__content
69if __name__ == "__main__":
70 # create a byte array a random bytes of len 20
72 my_bytes = bytearray(20)
73 for i in range(20):
74 my_bytes[i] = ord("a") + i
75 rewriter = Rewriter(my_bytes)
76 rewriter.replace(5, 10, b"hellooo")
77 rewriter.replace(5, 10, b" world")
78 rewriter.replace(0, 0, b"BEGIN")
79 s = rewriter.apply().decode(sys.getfilesystemencoding())
80 print(len(s))
81 print(s)