Still, let me try to summize as concisely as i can, and let me give you an example of what i meant by using unions.
In your original post, the two code blocks to me don't really correlate; The first, to me, seems pretty straightforward; a numeric header (sent as binary, hopefully as a full 8-bit-aligned packet) followed by data fitting in the specified bit lengths; now, if the header is uniform in length, you don't need to transmit the packet type's internal structure (i.e. the bit layout) since that exists on all sides, and based on the header received, the correct code will read in the correct amount of data and recombine it into the values you sent; perfectly clear.BorhilIan wrote: ↑Sun Mar 19, 2017 4:15 amSecond receive the packet.Code: Select all
net.Begin( "UpdatePlayer" ) - Converted to a numeric header for the packet and starts my packet assembler. (This method will allow custom net packets for modders to use) net.Write( 127 , 8 ) -- First is the value to send, Second is the number of bits. (Will be unsigned regardless no negative numbers needed) net.Send() - Send the packet to the specified targets on server or to server on client and clears the packet assembler. net.Broadcast() - Send the packet to all clients on the server except for specified. (would be called in place of 'net.Send()')
Thirdly this basic networking system will enable me to do the following.Code: Select all
net.Receive( "UpdatePlayer" , function() local value = net.Read( 8 ) -- Read the first eight bits which would return the 127 value. end )
Code: Select all
net.WriteString = function( txt ) net.Write( string.len( txt ) , 8 ) -- Send the length of the string up to 255 characters. for k , c in pairs( txt ) do net.write( string.byte( c ) , 8 ) -- Here would be a converter to binary from string. end end net.ReadString = function() local len = net.Read( 8 ) -- Read the length of the string from the first byte. local txt = {} for i = 1 , len do txt[ i ] = string.char( net.Read( 8 ) ) end return table.concat( txt ) end
Still, no computer or programming language handles anything on the level of individual bits; yes, you can do uneven-bit-fields and the like, especially with C structs, but it will need to be padded to byte-boundaries too, which you yourself acknowledge; how it looks internally / how it's handled internally is inconsequential.
As was said before, there are methods to pack variable bit-width values into 8-bit arrays. On the outside, it's still handled as an array, whether of bytes or chars, signed or unsigned.BorhilIan wrote: ↑Mon Mar 20, 2017 4:35 am Sorry i'm not very good at explaining things. The issues with networking data in cast strings is each character in that string is 1 byte. So lets say I just wanted to send a value which ranges from 0 - 16 (4 bits) I would effectively cast that to 1 byte (8 bits) if using strings to network data. Which would not be ideal for my desired application which involves lots of varidable range values being transferred.
This will indeed be my code example.
Code: Select all
local ffi = require("ffi")
ffi.cdef[[
typedef union {
double d;
char bytes[sizeof(double)];
} numbin;
]]
local magic = ffi.new("numbin", {})
magic.d = 53.34 -- lua number, which is a double, gets assigned to magic as a double.
print(ffi.string(magic.bytes, 8)) -- the same variable, magic, gets printed as 8 bytes, the width of a double.
Though luaJIT states that "Packed struct bitfields that cross container boundaries are not implemented." that doesn't mean that bitfields within container boundaries aren't; i haven't tested it myself, but basically, it would mean the following:
Code: Select all
local ffi = require("ffi")
-- The below struct would work, since 4+1+3 bits == 8 bits, which is the width of the char type.
ffi.cdef[[
typedef union {
struct {
char fourbit : 4;
char onebit : 1;
char threebit : 3;
} combined;
char bytes[sizeof(char)];
} numbin;
]]
-- The below goes over the underlying datatype's length boundary (here, uint_32_t) by one bit, so it'll probably error...
ffi.cdef[[
typedef union {
struct {
uint32_t a : 15;
uint32_t b : 7;
uint32_t c : 11;
} combined;
char bytes[sizeof(uint32_t)];
} numbin;
]]