From wikipedia, If the data is larger then MTU, The actual data is sent in multiple IP fragmented frames. If a fragment is lost, the entire UDP frame is considered lost, which ensures that the data is reassembled intact.
I assume the Rust function corresponds to the sendto function on Linux (and equivalent on windows) for which I can find no documentation indicating a return value not equal to either -1 or the length is possible.
Are you sure you really need to use the low-level socket api for your program? Using low level networking APIs without knowing it well and some experience is hard.
To answer your question:
So if I send 4096 bytes, there might be less number of bytes written ?
No, I don't think so. On success, it will return the number of bytes written (which is all of them), else an error.
Also from wikipadia, if MTU less then actual data, It signal with Datagram Too Big Error.
This might be due to the socket being configured for the messages to be sent atomically. From sendto(2):
The socket type requires that message be sent atomically, and the size of
the message to be sent made this impossible.
Also, if the don't fragment flag is set, and your MTU is big enough, that doesn't mean everyone else's in the path is as well. So despite your NIC having a big enough MTU you might still get ICMP 4 (frame too big) because the frame needs to be split up to fit into someone else's MTU along the path.
Again, getting low level networking right is hard, and if you don't really have to, don't. Use higher level protocols.