Nim data types

Builtin types

Numerical types

For integers, Nim offers uint8, uint16, uint32 and uint64 types as well as int8, int16, int32, int64 types.

Operations on signed integers are overflowed and underflowed checked unless the flag --overflowChecks:off is used.

Nim also offers int and uint types, which have the same size as the platform word size, so 4 bytes when compiled for 32-bit OS or 8 bytes for a 64-bit OS.

Conversion between int and int32 or int64 must be explicit except for string literals.

Integer literals default to int.

float32 and float64 maps to C float and double. float is an alias to float64 whether on a 32-bit or 64-bit platform

Binary blobs

Nim has a specific byte type which behaves like uint8.

It is the preferred type to represent binary blobs, i.e. we use seq[byte] over string, seq[char] or seq[uint8] for binary data.

Range types

Nim allows defining ranges of valid value which will be runtime checked everytime the value changes for example Nim defines by default type Natural = range[0 .. high(int)]. If the value of a Natural becomes less than 0 an RangeError exception will be thrown.

This is valuable to catch / prevent underflows.

Sequences

Sequences are heap-allocated containers similar to C++ vectors.

They have value-semantics and are copied on assignments.

Sequences have a data pointer, reserved memory and current length

Strings

Sequences are heap-allocated containers.

They have value-semantics and are copied on assignments.

Strings have a data pointer, reserved memory and current length.

The data is terminated by \0.

Nim strings automatically decays without copy to C strings in FFI calls

The representation is the same as a seq[byte] or seq[char] except for the terminating nul-byte, including within the GC tracking data structures Consequently, strings can be cast to seq[byte] but inversely casting seq[byte] to string will lead to non nul-terminated string in C FFI and buffer overflows.

Record / structs

Nim has 3 kinds of record types

  • Value

    type Foo = object
      field0: int
      field1: float
    
  • Reference

    type Foo = ref object
      field0: int
      field1: float
    
  • Pointer

    type Foo = ptr object
      field0: int
      field1: float
    

Value

A value object is allocated on the stack (unless if nested in heap-allocated types).

The equality check is structural.

Copy is done by copyMem (C memcpy)

Object variants do not have an equality operator set by default

Reference

A reference object is allocated on the heap and managed by the GC.

They are not thread-safe.

The equality check is by reference

Copy is done by copying the reference and increment the reference count

Pointer

A pointer object is manually managed, it can be on the heap (malloc) or on the stack (alloca)