hyunn

Binary Data๋ฅผ Swift ๊ตฌ์กฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ (feat. ByteBuffer, swift-nio) ๋ณธ๋ฌธ

Swift

Binary Data๋ฅผ Swift ๊ตฌ์กฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ (feat. ByteBuffer, swift-nio)

hyunn383 2024. 7. 27. 18:08

๋ชฉ์ฐจ

๐Ÿ’Œ Binary Data๋กœ ์„œ๋ฒ„์™€ ํ†ต์‹  (feat. ์†Œ์ผ“ ํ†ต์‹ )

๐ŸŒŸ Byte Buffer๋ž€?

๐ŸŽ Swift์—์„œ ByteBuffer๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ (๊ธฐ๋ณธ ์ž๋ฃŒํ˜•)

๐Ÿ ByteBuffer๋ฅผ ์‚ฌ์šฉํ•ด์„œ Swift ๊ตฌ์กฐ์ฒด(Struct)๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ


๐Ÿ’Œ Binary Data๋กœ ์„œ๋ฒ„์™€ ํ†ต์‹  (feat. ์†Œ์ผ“ ํ†ต์‹ )

์ตœ๊ทผ์— ์ฑ„ํŒ… ๊ธฐ๋Šฅ์„ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ, ์†Œ์ผ“(Socket) ํ†ต์‹ ์„ ๊ตฌํ˜„ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

(์†Œ์ผ“ ํ†ต์‹ ์— ๋Œ€ํ•ด์„œ๋Š” ์ฑ„ํŒ… ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ์ด ๋๋‚œ ํ›„ ํฌ์ŠคํŒ…ํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค.)

์ด๋ฒˆ์— ์†Œ์ผ“ ํ†ต์‹ ์„ ๊ตฌํ˜„ํ•˜๋ฉด์„œ, ํŠน์ด์ ์€ ์„œ๋ฒ„์™€ ํ†ต์‹ ํ• ๋•Œ ์ฃผ๊ณ ๋ฐ›๋Š” ๋ฐ์ดํ„ฐ ํ˜•์‹์ด Binary Data์˜€๋‹ค๋Š” ์ ์ด๋‹ค.

 

๋ฌผ๋ก , ์†Œ์ผ“ ํ†ต์‹ ๋„ json ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์•„๋„ ๋œ๋‹ค.

ํ•˜์ง€๋งŒ, ์†Œ์ผ“ ํ†ต์‹ ์˜ ๊ฒฝ์šฐ Binary Data๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š”๊ฒŒ ๋” ์ ํ•ฉํ•˜๋‹ค๊ณ  ํ•œ๋‹ค.

 

์ด์œ ๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ๊ฒ ์ง€๋งŒ ๋‘๊ฐ€์ง€๋งŒ ์ ๊ฒ ๋‹ค.

1. ํšจ์œจ์ ์ธ ๋ฐ์ดํ„ฐ ํฌ๊ธฐ

- ์šฐ์„  json์€ ๋ฌธ์ž์—ด์ด๋‹ค. json ๋ฌธ์ž์—ด์„ ์‹ค์ œ๋กœ ์„œ๋ฒ„์— ์ „์†ก๋ ๋•Œ๋Š” ๋ฐ”์ดํŠธ๋กœ ์ธ์ฝ”๋”ฉ ๋œ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์‹ค์ œ data๋งŒ byte๋กœ ๋ณด๋‚ด๋Š”๊ฒƒ ๋ณด๋‹ค, key๊ฐ’์„ ํฌํ•จํ•œ ๋ชจ๋“  data ๋ฌธ์ž์—ด์„ byte๋กœ ์ธ์ฝ”๋”ฉํ•˜๋ฉด ์šฉ๋Ÿ‰์ด ๋” ํด ์ˆ˜ ๋ฐ–์— ์—†๋‹ค.

2. ๋” ๋น ๋ฅธ ์†๋„์™€ ์„ฑ๋Šฅ

- Binary data๋Š” ์ปดํ“จํ„ฐ๊ฐ€ ์ง์ ‘ ์ฝ๊ณ  ์“ธ ์ˆ˜ ์žˆ๋Š” ์›์‹œ ํ˜•ํƒœ์ด๋ฏ€๋กœ, ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ๋” ๋น ๋ฅผ ์ˆ˜ ์žˆ๋‹ค.

- ๊ทธ์— ๋ฐ˜ํ•ด, JSON ๋ฐ์ดํ„ฐ๋Š” ๋ฌธ์ž์—ด๋กœ ํ‘œํ˜„๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ „์†กํ•˜๊ธฐ ์ „์— ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜, ์ˆ˜์‹  ํ›„ ๋ฌธ์ž์—ด์„ ํŒŒ์‹ฑํ•ด์•ผ ํ•œ๋‹ค. ์ด ๊ณผ์ •์€ ์ถ”๊ฐ€์ ์ธ CPU์™€ ๋ฉ”๋ชจ๋ฆฌ ์ž์›์„ ์†Œ๋ชจํ•˜๋ฉฐ, ์ „์†ก ์†๋„๋ฅผ ์ €ํ•˜์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.


๐ŸŒŸ Byte Buffer๋ž€?

Byte

๋ฐ”์ดํŠธ(Byte)๋Š” ๋””์ง€ํ„ธ ์ •๋ณด์˜ ๋‹จ์œ„ ์ค‘ ํ•˜๋‚˜๋กœ, 8๋น„ํŠธ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. ์ปดํ“จํ„ฐ์™€ ์ •๋ณด ํ†ต์‹  ๋ถ„์•ผ์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋ณธ์ ์ธ ๋ฐ์ดํ„ฐ ๋‹จ์œ„๋กœ, ๋ฌธ์ž, ์ˆซ์ž, ์ด๋ฏธ์ง€, ์‚ฌ์šด๋“œ ๋“ฑ์˜ ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

 

Buffer

๋ฒ„ํผ(Buffer)๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ž„์‹œ๋กœ ์ €์žฅํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์˜๋ฏธํ•œ๋‹ค. ๋ฒ„ํผ๋Š” ์ฃผ๋กœ ์„œ๋กœ ๋‹ค๋ฅธ ์†๋„๋กœ ์ž‘๋™ํ•˜๋Š” ์‹œ์Šคํ…œ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ ์ „์†ก์„ ์กฐ์ •ํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฅผ ์ž„์‹œ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

 

ByteBuffer

ByteBuffer๋Š” Java์—์„œ ์ œ๊ณตํ•˜๋Š” ํŠน์ • ํด๋ž˜์Šค์ด์ง€๋งŒ, "๋ฐ”์ดํŠธ ๋ฒ„ํผ"๋ผ๋Š” ๊ฐœ๋… ์ž์ฒด๋Š” Java์—๋งŒ ๊ตญํ•œ๋˜์ง€ ์•Š๊ณ , ๋‹ค์–‘ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์™€ ์‹œ์Šคํ…œ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ผ๋ฐ˜์ ์ธ ๊ฐœ๋…์ด๋‹ค. ๋ฐ”์ดํŠธ ๋ฒ„ํผ๋Š” ๋ฐ”์ดํŠธ ๋‹จ์œ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ž„์‹œ๋กœ ์ €์žฅํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์˜๋ฏธํ•œ๋‹ค.

 


๐ŸŽ Swift์—์„œ ByteBuffer๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ (๊ธฐ๋ณธ ์ž๋ฃŒํ˜•)

์šฐ์„ , ByteBuffer ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด Swift-nio ๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ด์ค˜์•ผํ•œ๋‹ค.

(cocoapods๋ฅผ ์ง€์› ์•ˆํ•˜๋‹ˆ, spm์œผ๋กœ ์„ค์น˜ํ•ด์•ผํ•œ๋‹ค.)

https://github.com/apple/swift-nio

 

GitHub - apple/swift-nio: Event-driven network application framework for high performance protocol servers & clients, non-blocki

Event-driven network application framework for high performance protocol servers & clients, non-blocking. - apple/swift-nio

github.com

 

swift-nio๋Š” ์ •๋ง ๋ฐฉ๋Œ€ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค. ์ •๋ง ๋งŽ์€๊ฑธ ์ง€์›ํ•˜์ง€๋งŒ, ByteBuffer๋ฅผ ์ฝ๊ณ  ์“ธ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ๋งŒ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

 

import NIO
// MARK: - ์„œ๋ฒ„์—์„œ ์‘๋‹ต ๋ฐ›์€ ๋ฐ์ดํ„ฐ
// WebSocket์œผ๋กœ data๋ฅผ receiveํ• ๋•Œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์€ Data ํƒ€์ž…์œผ๋กœ ๋“ค์–ด์˜จ๋‹ค.
let data: Data 

// MARK: - Data to byteBuffer
// ByteBuffer๋Š” SwiftNIO ํŒจํ‚ค์ง€์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” ๊ฐ์ฒด์ด๋‹ค.
var byteBuffer: ByteBuffer = ByteBuffer(data: data)

// MARK - ๋ฐ”์ดํŠธ ๋ฒ„ํผ ์ฝ๊ธฐ
// ๋ฐ”์ดํŠธ ๋ฒ„ํผ๋ฅผ ์•ž์—์„œ๋ถ€ํ„ฐ ์ฝ๊ฒŒ ๋œ๋‹ค.
// ๋ฐ”์ดํŠธ ๋ฒ„ํผ์˜ ์ฒซ ๋ฐ์ดํ„ฐ๋กœ Integer๊ฐ€ ๋“ค์–ด์˜จ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ , ์šฐ์„  Integer๋ฅผ ์ฝ์–ด๋ณด์ž.

// MARK: - byteBuffer to INT32 - Mid-Little
let int32 = byteBuffer.readInteger(endianness: .little, as: Int32.self)
// Int๋กœ ๋ฐ”๊พธ๊ธฐ
let int = Int(int32!)

// MARK: - ๋‹ค์Œ ๋ฐ”์ดํŠธ ๋ฒ„ํผ ์ฝ๊ธฐ
// ๋ฐ”์ดํŠธ ๋ฒ„ํผ๋ฅผ ๋˜ ์ฝ๊ฒŒ ๋˜๋ฉด ์•ž์— ์ฝ์€ Integer ๋‹ค์Œ ๋ถ€๋ถ„๋ถ€ํ„ฐ ์ฝ๊ฒŒ ๋œ๋‹ค.
// ๋‹ค์Œ ๋ฐ์ดํ„ฐ๋Š” String์ด ๋“ค์–ด์˜จ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ , String์„ ์ฝ์–ด๋ณด์ž.

// MARK: - String์„ ์ฝ์œผ๋ ค๋ฉด ์šฐ์„  String์˜ ๊ธธ์ด์ธ Integer๋ถ€ํ„ฐ ์ฝ์–ด์•ผํ•œ๋‹ค.
let strLength = byteBuffer.readInteger(endianness: .little, as: Int32.self)
// MARK: - byteBuffer to Ascii
let str = byteBuffer.readString(length: Int(strLength!), encoding: .ascii) 
// MARK: - ํ•œ๊ธ€๋„ ์ฝ์„๊ฑฐ๋ฉด utf8๋กœ ์ธ์ฝ”๋”ฉํ•˜๊ธฐ
let str = byteBuffer.readString(length: Int(strLength!), encoding: .utf8)

 

 

๐Ÿ“Œ ์—ฌ๊ธฐ์„œ ์ž ๊น! readInteger() ์— endianness์™€ as ์†์„ฑ์€ ๋ญ˜๊นŒ?

์ด๊ฑฐ.. ์ค‘์š”ํ•œ๊ฑฐ๋‹ค!

์™œ๋ƒํ•˜๋ฉด ์ด ์†์„ฑ์„ ์–ด๋–ป๊ฒŒ ์„ค์ •ํ•˜๋Š”์ง€์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค...

Endianness - ๋ฐ”์ดํŠธ ์ˆœ์„œ

์—”๋””์•ˆ ์†์„ฑ์€ ๋ฉ”๋ชจ๋ฆฌ ๋‚ด์—์„œ ๋ฐ์ดํ„ฐ์˜ ๋ฐ”์ดํŠธ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ฐฐ์—ด๋˜๋Š”์ง€๋ฅผ ์ •์˜ํ•œ๋‹ค.
1. ๋น… ์—”๋””์•ˆ (Big-endian):
๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋ฐ”์ดํŠธ(๊ฐ€์žฅ ๋†’์€ ๋ฐ”์ดํŠธ)๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์˜ ๋‚ฎ์€ ์ฃผ์†Œ์— ์ €์žฅ๋œ๋‹ค. ์ฆ‰, ๋ฐ์ดํ„ฐ์˜ ์ฒซ ๋ฒˆ์งธ ๋ฐ”์ดํŠธ๊ฐ€ ๊ฐ€์žฅ ๋จผ์ € ์ €์žฅ๋œ๋‹ค.
2. ๋ฆฌํ‹€ ์—”๋””์•ˆ (Little-endian):
๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋ฐ”์ดํŠธ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์˜ ๋†’์€ ์ฃผ์†Œ์— ์ €์žฅ๋œ๋‹ค. ์ฆ‰, ๋ฐ์ดํ„ฐ์˜ ๋งˆ์ง€๋ง‰ ๋ฐ”์ดํŠธ๊ฐ€ ๊ฐ€์žฅ ๋จผ์ € ์ €์žฅ๋œ๋‹ค.

As - ํ˜•๋ณ€ํ™˜

As ์†์„ฑ์€ readInteger() ๋ฉ”์„œ๋“œ๊ฐ€ ์ฝ์€ ๋ฐ์ดํ„ฐ๋ฅผ ํŠน์ • ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ์ฝํž ๋•Œ, ์–ด๋–ป๊ฒŒ ํ•ด์„๋ ์ง€๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์ด๋‹ค.

 

 

๋‚ด๊ฐ€ ์‘๋‹ต๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ค ์†์„ฑ์œผ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ๋ ์ง€ ๋ชจ๋ฅธ๋‹ค๋ฉด, (๋‚˜๋Š” ์•Œ๋ ค์ฃผ๋Š” ์‚ฌ๋žŒ์ด ์—†์–ด์„œ ๋ชฐ๋ž๋‹ค...)

์‘๋‹ต ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ˜์†”์—์„œ ์ฐ์–ด๋ณด๊ณ , ์ฐํžŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ปจ๋ฒ„ํ„ฐ์—์„œ ๋Œ๋ ค๋ณด๊ณ  ๋งž๋Š” ์†์„ฑ์„ ์ฐพ๋Š”๋‹ค!!

https://www.scadacore.com/tools/programming-calculators/online-hex-converter/

 

Online Hex Converter - Bytes, Ints, Floats, Significance, Endians - SCADACore

Convert Hex values into Bytes, Ints, and Floats of different bit significance, Bit Endians, and byte significance for interfacing with unknown field devices

www.scadacore.com

๋‚ด๊ฐ€ ์‚ฌ์šฉํ•œ ์ปจ๋ฒ„ํ„ฐ์ด๋‹ค. 

์™œ Hex Converter๋ƒ๊ณ ? Hex String์€ Binary Data๋ฅผ ์‚ฌ๋žŒ์ด ๋ณด๊ธฐ ์ข‹๊ฒŒ ๋ณ€ํ™˜ํ•œ ๊ฒƒ์ด๋‹ค.

๋‚˜๋Š” ์‘๋‹ต์œผ๋กœ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ˜์†”์— ์ฐ์œผ๋ฉด [01 00 00 00] ์ด ๋‚˜์™”๋‹ค.

์ด๊ฑด binary data๋ฅผ ์‚ฌ๋žŒ์ด ๋ณด๊ธฐ ์ข‹๊ฒŒ ๋ณ€ํ™˜ํ•ด๋†“์€ Hex String์ด์—ˆ๊ณ , ๋”ฐ๋ผ์„œ Hex String Converter ๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

 

๋‚˜๋Š” ๋ณ€ํ™˜ํ–ˆ์„๋•Œ ๊ฐ’์ด 1์ด์—ฌ์•ผ ํ–ˆ๋‹ค.

1์„ ์ฐพ์•„๋ณด๋ฉด, Int32 - Little Endian (DCBA) ์™€ UINT16 - Little Endian (BA) ๊ฐ€ ์žˆ๋‹ค.

์ด์ค‘์—์„œ ๋‚˜๋Š” Int32 - Little Endian์œผ๋กœ ๋ณ€ํ™˜ํ–ˆ๊ณ , ๋ฐ์ดํ„ฐ๋ฅผ ์ž˜ ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

let int32 = byteBuffer.readInteger(endianness: .little, as: Int32.self)

๐Ÿ ByteBuffer๋ฅผ ์‚ฌ์šฉํ•ด์„œ Swift ๊ตฌ์กฐ์ฒด(Struct)๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ

struct BaseResponse<T> {
    var res: Int?
    var code: Int?
    var data: T?
}

struct ChattingRooms {
    var chattingRooms: [ChattingRoom]?
}

struct ChattingRoom {
    var id: String?
    var name: String?
    var groupId: String?
    var channelId: String?
    var imageUrl: String?
    var lastChat: String?
    var lastChatTimeStamp: Int?
    var unreadMessageCount: Int?
}

 

 

์‘๋‹ต๋ฐ›์€ Binary Data๋ฅผ Swift๋กœ ์ฝ๊ธฐ ํŽธํ•˜๊ฒŒ ์œ„์™€ ๊ฐ™์€ ๊ตฌ์กฐ์ฒด(Struct)๋กœ ๋ณ€ํ™˜ํ•ด๋ณด์ž!

let res = byteBuffer.readInteger(endianness: .little, as: Int32.self) 
let code = byteBuffer.readInteger(endianness: .little, as: Int32.self)

// MARK: - data๋Š” object Array๋กœ ๋“ค์–ด์˜ค๊ธฐ ๋•Œ๋ฌธ์— ์šฐ์„ , length๋ถ€ํ„ฐ ๊ตฌํ•œ๋‹ค.
let objectArrayLength = byteBuffer.readInteger(endianness: .little, as: Int32.self)

var data: [ChattingRoom] = []

// MARK: - ๋ฐฐ์—ด ๊ธธ์ด๋งŒํผ object๋ฅผ ์ฝ๋Š”๋‹ค.
if let objectArrayLength = objectArrayLength {
    for _ in 0..<objectArrayLength {
        if let object = readObject(byteBuffer: byteBuffer) {
            data.append(object)
        }
    }
}

// MARK: - ์ตœ์ข… ๊ตฌ์กฐ์ฒด(Struct)
let response: BaseResponse<ChattingRooms> = BaseResponse(res: Int(res!), code: Int(code!), data: ChattingRooms(chattingRooms: data))

print(response)
// MARK: - object๋ฅผ ์ฝ์–ด ChattingRoom ๊ตฌ์กฐ์ฒด๋กœ ๋ณ€ํ™˜
private func readObject(byteBuffer: ByteBuffer) -> ChattingRoom {
    var byteBuffer = byteBuffer

    let idLength = byteBuffer.readInteger(endianness: .little, as: Int32.self)
    let id = byteBuffer.readString(length: Int(idLength!), encoding: .ascii)

    let nameLength = byteBuffer.readInteger(endianness: .little, as: Int32.self)
    let name = byteBuffer.readString(length: Int(nameLength!), encoding: .utf8)

    let groupIdLength = byteBuffer.readInteger(endianness: .little, as: Int32.self)
    let groupId = byteBuffer.readString(length: Int(groupIdLength!), encoding: .ascii)

    let channelIdLength = byteBuffer.readInteger(endianness: .little, as: Int32.self)
    let channelId = byteBuffer.readString(length: Int(channelIdLength!), encoding: .ascii)

    let imageUrlLength = byteBuffer.readInteger(endianness: .little, as: Int32.self)
    let imageUrl = byteBuffer.readString(length: Int(imageUrlLength!), encoding: .ascii)

    let lastChatLength = byteBuffer.readInteger(endianness: .little, as: Int32.self)
    let lastChat = byteBuffer.readString(length: Int(lastChatLength!), encoding: .utf8)

    let lastChatTimeStamp = byteBuffer.readInteger(endianness: .little, as: Int32.self)

    let unreadMessageCount = byteBuffer.readInteger(endianness: .little, as: Int32.self)

    return ChattingRoom(id: id, name: name, groupId: groupId, channelId: channelId, imageUrl: imageUrl, lastChat: lastChat, lastChatTimeStamp: Int(lastChatTimeStamp!), unreadMessageCount: Int(unreadMessageCount!))
}