diff options
author | bptato <nincsnevem662@gmail.com> | 2022-12-10 22:50:23 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2022-12-10 22:50:23 +0100 |
commit | 940325abfc9714b06de920a2a7f8911eae22f357 (patch) | |
tree | 9651d5f1d22e3eaa6b098b6bbed97a583244375d | |
parent | 5c267ce6c9c1add997767f5eaad248cdd829c6fc (diff) | |
download | chawan-940325abfc9714b06de920a2a7f8911eae22f357.tar.gz |
Fix blocking socketstream recv/send, clean up ips/serialize & types/color
Write always blocks for now, as it's too big of a footgun not to
-rw-r--r-- | src/buffer/cell.nim | 8 | ||||
-rw-r--r-- | src/css/values.nim | 3 | ||||
-rw-r--r-- | src/display/pager.nim | 2 | ||||
-rw-r--r-- | src/display/term.nim | 8 | ||||
-rw-r--r-- | src/io/loader.nim | 2 | ||||
-rw-r--r-- | src/ips/serialize.nim | 370 | ||||
-rw-r--r-- | src/ips/socketstream.nim | 17 | ||||
-rw-r--r-- | src/types/color.nim | 88 |
8 files changed, 289 insertions, 209 deletions
diff --git a/src/buffer/cell.nim b/src/buffer/cell.nim index d7de064f..a5e33645 100644 --- a/src/buffer/cell.nim +++ b/src/buffer/cell.nim @@ -190,7 +190,7 @@ proc handleAnsiCode(format: var Format, final: char, params: string) = of 25: format.blink = false of 27: format.reverse = false of 29: format.strike = false - of 30..37: format.fgcolor = CellColor(rgb: false, color: uint8(ip[pi])) + of 30..37: format.fgcolor = uint8(ip[pi]).cellColor() of 38: inc pi if pi < ip.len: @@ -202,7 +202,7 @@ proc handleAnsiCode(format: var Format, final: char, params: string) = let g = ip[pi] inc pi let b = ip[pi] - format.fgcolor = CellColor(rgb: true, rgbcolor: rgb(r, g, b)) + format.fgcolor = rgb(r, g, b).cellColor() else: #TODO inc pi @@ -212,7 +212,7 @@ proc handleAnsiCode(format: var Format, final: char, params: string) = of 39: format.fgcolor = defaultColor of 40..47: - format.bgcolor = CellColor(rgb: false, color: uint8(ip[0])) + format.bgcolor = uint8(ip[0]).cellColor() of 48: inc pi if pi < ip.len: @@ -224,7 +224,7 @@ proc handleAnsiCode(format: var Format, final: char, params: string) = let g = ip[pi] inc pi let b = ip[pi] - format.bgcolor = CellColor(rgb: true, rgbcolor: rgb(r, g, b)) + format.bgcolor = rgb(r, g, b).cellColor() else: #TODO inc pi diff --git a/src/css/values.nim b/src/css/values.nim index 66704d36..6d92807a 100644 --- a/src/css/values.nim +++ b/src/css/values.nim @@ -420,9 +420,6 @@ func cssColor(val: CSSComponentValue): RGBAColor = else: discard raise newException(CSSValueError, "Invalid color") -func cellColor*(color: RGBAColor): CellColor = - return CellColor(rgb: true, rgbcolor: RGBColor(color)) - func isToken(d: CSSDeclaration): bool {.inline.} = d.value.len > 0 and d.value[0] of CSSToken func cssLength(d: CSSDeclaration): CSSLength = diff --git a/src/display/pager.nim b/src/display/pager.nim index 3bf330e6..adec0d9e 100644 --- a/src/display/pager.nim +++ b/src/display/pager.nim @@ -183,7 +183,7 @@ proc refreshDisplay(pager: Pager, container = pager.container) = var by = 0 pager.clearDisplay() var hlformat = newFormat() - hlformat.bgcolor = CellColor(rgb: true, rgbcolor: pager.config.hlcolor) + hlformat.bgcolor = pager.config.hlcolor.cellColor() for line in container.ilines(container.fromy ..< min(container.fromy + pager.display.height, container.numLines)): var w = 0 # width of the row so far var i = 0 # byte in line.str diff --git a/src/display/term.nim b/src/display/term.nim index fcb76692..4a166c90 100644 --- a/src/display/term.nim +++ b/src/display/term.nim @@ -192,13 +192,13 @@ proc distance(a, b: CellColor): float = proc invert(color: CellColor, bg: bool): CellColor = if color == defaultColor: if bg: - return CellColor(rgb: true, rgbcolor: ColorsRGB["white"]) + return ColorsRGB["white"].cellColor() else: - return CellColor(rgb: true, rgbcolor: ColorsRGB["black"]) + return ColorsRGB["black"].cellColor() elif color.rgb: - return CellColor(rgb: true, rgbcolor: RGBColor(0xFFFFFF - uint32(color.rgbcolor))) + return RGBColor(0xFFFFFF - cast[uint32](color.rgbcolor)).cellColor() else: - return CellColor(rgb: true, rgbcolor: RGBColor(0xFFFFFF - uint32(ANSIColorMap[color.color mod 10]))) + return RGBColor(0xFFFFFF - uint32(ANSIColorMap[color.color mod 10])).cellColor() # Use euclidian distance to quantize RGB colors. proc approximateANSIColor(rgb: RGBColor, exclude = -1): int = diff --git a/src/io/loader.nim b/src/io/loader.nim index 7436d174..150831a0 100644 --- a/src/io/loader.nim +++ b/src/io/loader.nim @@ -107,7 +107,7 @@ proc runFileLoader*(fd: cint, defaultHeaders: HeaderList) = case cmd of LOAD: var request: Request - stream.read(request) + stream.sread(request) for k, v in defaultHeaders.table: if k notin request.headers.table: request.headers.table[k] = v diff --git a/src/ips/serialize.nim b/src/ips/serialize.nim index 09754466..73320b27 100644 --- a/src/ips/serialize.nim +++ b/src/ips/serialize.nim @@ -1,6 +1,7 @@ # Write data to streams. import options +import sets import streams import tables @@ -8,152 +9,122 @@ import buffer/cell import io/request import js/regex import types/buffersource -import types/color import types/url -proc slen*[T](o: T): int = - when T is string: - return slen(o.len) + o.len - elif T is bool: - return sizeof(char) - elif T is URL: - return ($o).slen - elif T is seq: - result = slen(o.len) - for x in o: - result += slen(x) - elif T is Option: - result = slen(o.isSome) - if o.isSome: - result += slen(o.get) - elif T is MimePart: - result += slen(o.isFile) - result += slen(o.name) - result += slen(o.content) - if o.isFile: - result += slen(o.filename) - result += slen(o.contentType) - result += slen(o.fileSize) - result += slen(o.isStream) - elif T is Request: - result += slen(o.httpmethod) - result += slen(o.url) - result += slen(o.headers) - result += slen(o.body) - result += slen(o.multipart) - elif T is CellColor: - result += slen(o.rgb) - if o.rgb: - result += slen(o.rgbcolor) - else: - result += slen(o.color) - elif T is Regex: - result += slen(o.plen) - result += o.plen - result += slen(o.buf) - elif T is BufferSource: - result += slen(o.t) - case o.t - of CLONE: result += slen(o.clonepid) - of LOAD_REQUEST: result += slen(o.request) - of LOAD_PIPE: result += slen(o.fd) - result += slen(o.location) - result += slen(o.contenttype) - elif T is tuple: - for f in o.fields: - result += slen(f) - elif T is object: - for f in o.fields: - result += slen(f) - elif T is ref object: - result += slen(o[]) - else: - result += sizeof(o) +proc swrite*(stream: Stream, n: SomeNumber) +proc sread*(stream: Stream, n: var SomeNumber) +func slen*(n: SomeNumber): int -template swrite*[T](stream: Stream, o: T) = - stream.write(o) +proc swrite*[T](stream: Stream, s: set[T]) +proc sread*[T](stream: Stream, s: var set[T]) +func slen*[T](s: set[T]): int -proc swrite*(stream: Stream, s: string) = - stream.swrite(s.len) - stream.write(s) +proc swrite*[T: enum](stream: Stream, x: T) +proc sread*[T: enum](stream: Stream, x: var T) +func slen*[T: enum](x: T): int -proc swrite*(stream: Stream, b: bool) = - if b: - stream.swrite(1u8) - else: - stream.swrite(0u8) +proc swrite*(stream: Stream, s: string) +proc sread*(stream: Stream, s: var string) +func slen*(s: string): int -proc swrite*(stream: Stream, url: Url) = - stream.swrite(url.serialize()) +proc swrite*(stream: Stream, b: bool) +proc sread*(stream: Stream, b: var bool) +func slen*(b: bool): int -proc swrite*(stream: Stream, tup: tuple) = - for f in tup.fields: - stream.swrite(f) +proc swrite*(stream: Stream, url: Url) +proc sread*(stream: Stream, url: var Url) +func slen*(url: Url): int -proc swrite*[T](stream: Stream, s: seq[T]) = - stream.swrite(s.len) - for m in s: - stream.swrite(m) +proc swrite*(stream: Stream, tup: tuple) +proc sread*(stream: Stream, tup: var tuple) +func slen*(tup: tuple): int -proc swrite*[U, V](stream: Stream, t: Table[U, V]) = - stream.swrite(t.len) - for k, v in t: - stream.swrite(k) - stream.swrite(v) +proc swrite*[T](stream: Stream, s: seq[T]) +proc sread*[T](stream: Stream, s: var seq[T]) +func slen*(s: seq): int -proc swrite*(stream: Stream, obj: object) = - for f in obj.fields: - stream.swrite(f) +proc swrite*[U, V](stream: Stream, t: Table[U, V]) +proc sread*[U, V](stream: Stream, t: var Table[U, V]) +func slen*[U, V](t: Table[U, V]): int -proc swrite*(stream: Stream, obj: ref object) = - stream.swrite(obj[]) +proc swrite*(stream: Stream, obj: object) +proc sread*(stream: Stream, obj: var object) +func slen*(obj: object): int -proc swrite*(stream: Stream, part: MimePart) = - stream.swrite(part.isFile) - stream.swrite(part.name) - stream.swrite(part.content) - if part.isFile: - stream.swrite(part.filename) - stream.swrite(part.contentType) - stream.swrite(part.fileSize) - stream.swrite(part.isStream) +proc swrite*(stream: Stream, obj: ref object) +proc sread*(stream: Stream, obj: var ref object) +func slen*(obj: ref object): int -proc swrite*[T](stream: Stream, o: Option[T]) = - stream.swrite(o.issome) - if o.issome: - stream.swrite(o.get) +proc swrite*(stream: Stream, part: MimePart) +proc sread*(stream: Stream, part: var MimePart) +func slen*(part: MimePart): int -proc swrite*(stream: Stream, request: Request) = - stream.swrite(request[]) +proc swrite*[T](stream: Stream, o: Option[T]) +proc sread*[T](stream: Stream, o: var Option[T]) +func slen*[T](o: Option[T]): int -proc swrite*(stream: Stream, color: CellColor) = - stream.swrite(color.rgb) - if color.rgb: - stream.swrite(color.rgbcolor) - else: - stream.swrite(color.color) +proc swrite*(stream: Stream, regex: Regex) +proc sread*(stream: Stream, regex: var Regex) +func slen*(regex: Regex): int -proc swrite*(stream: Stream, regex: Regex) = - stream.swrite(regex.plen) - stream.writeData(regex.bytecode, regex.plen) - stream.swrite(regex.buf) +proc swrite*(stream: Stream, source: BufferSource) +proc sread*(stream: Stream, source: var BufferSource) +func slen*(source: BufferSource): int -proc swrite*(stream: Stream, source: BufferSource) = - stream.swrite(source.t) - case source.t - of CLONE: stream.swrite(source.clonepid) - of LOAD_REQUEST: stream.swrite(source.request) - of LOAD_PIPE: stream.swrite(source.fd) - stream.swrite(source.location) - stream.swrite(source.contenttype) +proc swrite*(stream: Stream, n: SomeNumber) = + stream.write(n) + +proc sread*(stream: Stream, n: var SomeNumber) = + stream.read(n) -template sread*[T](stream: Stream, o: T) = - stream.read(o) +func slen*(n: SomeNumber): int = + return sizeof(n) + +proc swrite*[T: enum](stream: Stream, x: T) = + stream.swrite(cast[int](x)) + +proc sread*[T: enum](stream: Stream, x: var T) = + var i: int + stream.sread(i) + x = cast[T](i) + +func slen*[T: enum](x: T): int = + return sizeof(int) + +proc swrite*[T](stream: Stream, s: set[T]) = + stream.swrite(s.card) + for e in s: + stream.swrite(e) + +proc sread*[T](stream: Stream, s: var set[T]) = + var len: int + stream.sread(len) + for i in 0 ..< len: + var x: T + stream.sread(x) + s.incl(x) + +func slen*[T](s: set[T]): int = + result = slen(s.card) + for x in s: + result += slen(x) + +proc swrite*(stream: Stream, s: string) = + stream.swrite(s.len) + stream.write(s) proc sread*(stream: Stream, s: var string) = var len: int stream.sread(len) stream.readStr(len, s) +func slen*(s: string): int = + slen(s.len) + s.len + +proc swrite*(stream: Stream, b: bool) = + if b: + stream.swrite(1u8) + else: + stream.swrite(0u8) proc sread*(stream: Stream, b: var bool) = var n: uint8 @@ -164,6 +135,39 @@ proc sread*(stream: Stream, b: var bool) = assert n == 0u8 b = false +func slen*(b: bool): int = + return sizeof(uint8) + +proc swrite*(stream: Stream, url: Url) = + stream.swrite(url.serialize()) + +proc sread*(stream: Stream, url: var Url) = + var s: string + stream.sread(s) + url = newURL(s) + +func slen*(url: Url): int = + slen(url.serialize()) + +proc swrite*(stream: Stream, tup: tuple) = + for f in tup.fields: + stream.swrite(f) + +proc sread*(stream: Stream, tup: var tuple) = + for f in tup.fields: + stream.sread(f) + +func slen*(tup: tuple): int = + for f in tup.fields: + result += slen(f) + +proc swrite*[T](stream: Stream, s: seq[T]) = + stream.swrite(s.len) + var i = 0 + for m in s: + stream.swrite(m) + inc i + proc sread*[T](stream: Stream, s: var seq[T]) = var len: int stream.sread(len) @@ -171,15 +175,16 @@ proc sread*[T](stream: Stream, s: var seq[T]) = for i in 0..<len: stream.sread(s[i]) -proc sread*[T](stream: Stream, o: var Option[T]) = - var x: bool - stream.sread(x) - if x: - var m: T - stream.sread(m) - o = some(m) - else: - o = none(T) +func slen*(s: seq): int = + result = slen(s.len) + for x in s: + result += slen(x) + +proc swrite*[U, V](stream: Stream, t: Table[U, V]) = + stream.swrite(t.len) + for k, v in t: + stream.swrite(k) + stream.swrite(v) proc sread*[U, V](stream: Stream, t: var Table[U, V]) = var len: int @@ -191,22 +196,43 @@ proc sread*[U, V](stream: Stream, t: var Table[U, V]) = stream.sread(v) t[k] = v +func slen*[U, V](t: Table[U, V]): int = + result = slen(t.len) + for k, v in t: + result += slen(k) + result += slen(v) + +proc swrite*(stream: Stream, obj: object) = + for f in obj.fields: + stream.swrite(f) + proc sread*(stream: Stream, obj: var object) = for f in obj.fields: stream.sread(f) -proc sread*(stream: Stream, tup: var tuple) = - for f in tup.fields: - stream.sread(f) +func slen*(obj: object): int = + for f in obj.fields: + result += slen(f) + +proc swrite*(stream: Stream, obj: ref object) = + stream.swrite(obj[]) -proc read*(stream: Stream, obj: var ref object) = +proc sread*(stream: Stream, obj: var ref object) = new(obj) stream.sread(obj[]) -proc sread*(stream: Stream, url: var Url) = - var s: string - stream.sread(s) - url = newURL(s) +func slen*(obj: ref object): int = + slen(obj[]) + +proc swrite*(stream: Stream, part: MimePart) = + stream.swrite(part.isFile) + stream.swrite(part.name) + stream.swrite(part.content) + if part.isFile: + stream.swrite(part.filename) + stream.swrite(part.contentType) + stream.swrite(part.fileSize) + stream.swrite(part.isStream) proc sread*(stream: Stream, part: var MimePart) = var isFile: bool @@ -223,15 +249,40 @@ proc sread*(stream: Stream, part: var MimePart) = stream.sread(part.fileSize) stream.sread(part.isStream) -proc sread*(stream: Stream, color: var CellColor) = - var rgb: bool - stream.sread(rgb) - if rgb: - color = CellColor(rgb: true) - stream.sread(color.rgbcolor) +func slen*(part: MimePart): int = + result += slen(part.isFile) + result += slen(part.name) + result += slen(part.content) + if part.isFile: + result += slen(part.filename) + result += slen(part.contentType) + result += slen(part.fileSize) + result += slen(part.isStream) + +proc swrite*[T](stream: Stream, o: Option[T]) = + stream.swrite(o.issome) + if o.isSome: + stream.swrite(o.get) + +proc sread*[T](stream: Stream, o: var Option[T]) = + var x: bool + stream.sread(x) + if x: + var m: T + stream.sread(m) + o = some(m) else: - color = CellColor(rgb: false) - stream.sread(color.color) + o = none(T) + +func slen*[T](o: Option[T]): int = + result = slen(o.isSome) + if o.isSome: + result += slen(o.get) + +proc swrite*(stream: Stream, regex: Regex) = + stream.swrite(regex.plen) + stream.writeData(regex.bytecode, regex.plen) + stream.swrite(regex.buf) proc sread*(stream: Stream, regex: var Regex) = assert regex.bytecode == nil @@ -243,6 +294,20 @@ proc sread*(stream: Stream, regex: var Regex) = if l != regex.plen: `=destroy`(regex) +func slen*(regex: Regex): int = + result += slen(regex.plen) + result += regex.plen + result += slen(regex.buf) + +proc swrite*(stream: Stream, source: BufferSource) = + stream.swrite(source.t) + case source.t + of CLONE: stream.swrite(source.clonepid) + of LOAD_REQUEST: stream.swrite(source.request) + of LOAD_PIPE: stream.swrite(source.fd) + stream.swrite(source.location) + stream.swrite(source.contenttype) + proc sread*(stream: Stream, source: var BufferSource) = var t: BufferSourceType stream.sread(t) @@ -258,3 +323,12 @@ proc sread*(stream: Stream, source: var BufferSource) = stream.sread(source.fd) stream.sread(source.location) stream.sread(source.contenttype) + +func slen*(source: BufferSource): int = + result += slen(source.t) + case source.t + of CLONE: result += slen(source.clonepid) + of LOAD_REQUEST: result += slen(source.request) + of LOAD_PIPE: result += slen(source.fd) + result += slen(source.location) + result += slen(source.contenttype) diff --git a/src/ips/socketstream.nim b/src/ips/socketstream.nim index c0abf07f..5d0485fa 100644 --- a/src/ips/socketstream.nim +++ b/src/ips/socketstream.nim @@ -11,12 +11,16 @@ import ips/serversocket type SocketStream* = ref object of Stream source*: Socket - recvw*: bool + blk*: bool isend: bool proc sockReadData(s: Stream, buffer: pointer, len: int): int = let s = SocketStream(s) - result = s.source.recv(buffer, len) + if s.blk: + while result < len: + result += s.source.recv(cast[pointer](cast[int](buffer) + result), len - result) + else: + result = s.source.recv(buffer, len) if result < 0: if errno == EAGAIN: raise newException(ErrorAgain, "") @@ -30,7 +34,10 @@ proc sockReadData(s: Stream, buffer: pointer, len: int): int = s.isend = true proc sockWriteData(s: Stream, buffer: pointer, len: int) = - discard SocketStream(s).source.send(buffer, len) + #TODO maybe don't block if blk is false? + var i = 0 + while i < len: + i += SocketStream(s).source.send(cast[pointer](cast[int](buffer) + i), len - i) proc sockAtEnd(s: Stream): bool = SocketStream(s).isend @@ -94,6 +101,7 @@ func newSocketStream*(): SocketStream = proc connectSocketStream*(path: string, buffered = true, blocking = true): SocketStream = result = newSocketStream() + result.blk = blocking let sock = newSocket(Domain.AF_UNIX, SockType.SOCK_STREAM, Protocol.IPPROTO_IP, buffered) #if not blocking: # sock.getFd().setBlocking(false) @@ -106,8 +114,9 @@ proc connectSocketStream*(pid: Pid, buffered = true, blocking = true): SocketStr except OSError: return nil -proc acceptSocketStream*(ssock: ServerSocket): SocketStream = +proc acceptSocketStream*(ssock: ServerSocket, blocking = true): SocketStream = result = newSocketStream() + result.blk = blocking var sock: Socket ssock.sock.accept(sock, inheritable = true) result.source = sock diff --git a/src/types/color.nim b/src/types/color.nim index 3e29c15f..dbd2e4fd 100644 --- a/src/types/color.nim +++ b/src/types/color.nim @@ -7,52 +7,54 @@ import tables import utils/twtstr type - RGBColor* = distinct int32 + RGBColor* = distinct uint32 - RGBAColor* = distinct int32 + RGBAColor* = distinct uint32 CellColor* = object - case rgb*: bool - of true: - rgbcolor*: RGBColor - of false: - color*: uint8 + rgb*: bool + n: uint32 converter toRGBColor*(i: RGBAColor): RGBColor = - return RGBColor(int32(i) and 0xFFFFFFi32) + return RGBColor(uint32(i) and 0xFFFFFFu32) converter toRGBAColor*(i: RGBColor): RGBAColor = - return RGBAColor(int32(i) or 0xFF000000i32) + return RGBAColor(uint32(i) or 0xFF000000u32) -func `==`*(color1, color2: CellColor): bool = - if color1.rgb != color2.rgb: - return false - if color1.rgb: - return int(color1.rgbcolor) == int(color2.rgbcolor) - return color1.color == color2.color +func rgbcolor*(color: CellColor): RGBColor = + cast[RGBColor](color.n) -const defaultColor* = CellColor(rgb: false, color: 0) +func color*(color: CellColor): uint8 = + cast[uint8](color.n) + +func cellColor*(rgb: RGBColor): CellColor = + return CellColor(rgb: true, n: uint32(rgb)) + +func cellColor*(c: uint8): CellColor = + return CellColor(rgb: true, n: uint32(c)) + +const defaultColor* = CellColor(rgb: false, n: 0) const ColorsANSIFg* = [ - CellColor(rgb: false, color: 30), # black - CellColor(rgb: false, color: 31), # red - CellColor(rgb: false, color: 32), # green - CellColor(rgb: false, color: 33), # yellow - CellColor(rgb: false, color: 34), # blue - CellColor(rgb: false, color: 35), # magenta - CellColor(rgb: false, color: 36), # cyan - CellColor(rgb: false, color: 37), # white + CellColor(rgb: false, n: 30), # black + CellColor(rgb: false, n: 31), # red + CellColor(rgb: false, n: 32), # green + CellColor(rgb: false, n: 33), # yellow + CellColor(rgb: false, n: 34), # blue + CellColor(rgb: false, n: 35), # magenta + CellColor(rgb: false, n: 36), # cyan + CellColor(rgb: false, n: 37), # white ] const ColorsANSIBg* = [ - CellColor(rgb: false, color: 40), # black - CellColor(rgb: false, color: 41), # red - CellColor(rgb: false, color: 42), # green - CellColor(rgb: false, color: 43), # yellow - CellColor(rgb: false, color: 44), # blue - CellColor(rgb: false, color: 45), # magenta - CellColor(rgb: false, color: 46), # cyan - CellColor(rgb: false, color: 47), # white + CellColor(rgb: false, n: 40), # black + CellColor(rgb: false, n: 41), # red + CellColor(rgb: false, n: 42), # green + CellColor(rgb: false, n: 43), # yellow + CellColor(rgb: false, n: 44), # blue + CellColor(rgb: false, n: 45), # magenta + CellColor(rgb: false, n: 46), # cyan + CellColor(rgb: false, n: 47), # white ] const ColorsRGB* = { @@ -283,37 +285,35 @@ func parseLegacyColor*(s: string): Option[RGBColor] = return some(RGBColor(c)) func r*(c: RGBAColor): int = - return int(int32(c) shr 16 and 0xff) + return int(uint32(c) shr 16 and 0xff) func g*(c: RGBAColor): int = - return int(int32(c) shr 8 and 0xff) + return int(uint32(c) shr 8 and 0xff) func b*(c: RGBAColor): int = - return int(int32(c) and 0xff) + return int(uint32(c) and 0xff) func a*(c: RGBAColor): int = - return int(int32(c) shr 24 and 0xff) + return int(uint32(c) shr 24 and 0xff) func rgb*(r, g, b: int): RGBColor = return RGBColor((r shl 16) or (g shl 8) or b) -func `==`*(a, b: RGBAColor): bool = - return int32(a) == int32(b) - +func `==`*(a, b: RGBAColor): bool {.borrow.} func r*(c: RGBColor): int = - return int(int32(c) shr 16 and 0xff) + return int(uint32(c) shr 16 and 0xff) func g*(c: RGBColor): int = - return int(int32(c) shr 8 and 0xff) + return int(uint32(c) shr 8 and 0xff) func b*(c: RGBColor): int = - return int(int32(c) and 0xff) + return int(uint32(c) and 0xff) func rgba*(r, g, b, a: int): RGBAColor = - return RGBAColor((int32(a) shl 24) or (int32(r) shl 16) or (int32(g) shl 8) or int32(b)) + return RGBAColor((uint32(a) shl 24) or (uint32(r) shl 16) or (uint32(g) shl 8) or uint32(b)) -func `$`*(color: CellColor): string = +template `$`*(color: CellColor): string = if color.rgb: "r" & $color.rgbcolor.r & "g" & $color.rgbcolor.g & "b" & $color.rgbcolor.b else: |