এলিক্সির বাইনারি ডেটা নিয়ে কাজ করার জন্য একটি সুন্দর সিনট্যাক্স দেয়, যেমনটি আমরা বিটস্ট্রিং নিয়ে কাজ করার জন্য দেওয়া <<>> স্পেশাল ফর্মে দেখেছি।
বাইনারি টাইপটি বিটস্ট্রিং টাইপের একটি বিশেষ রূপ। বিটস্ট্রিং যেকোনো দৈর্ঘ্যের হতে পারে (বিট-এর যেকোনো সংখ্যা), কিন্তু বাইনারি সেখানেই, যেখানে বিটের সংখ্যাকে ৮ দিয়ে নিঃশেষে ভাগ করা যায়। অর্থাৎ, বাইনারি নিয়ে কাজ করার সময় আমরা প্রায়ই সবকিছুকে বাইট (৮ বিট) হিসেবে ভাবি। একটি বাইট 0 থেকে 255 পর্যন্ত ইন্টিজার সংখ্যা প্রকাশ করতে পারে। হেক্সাডেসিমেল-এ বাইট মান নিয়ে কাজ করা কমন, 0x00 - 0xFF.
বাইনারি লিটারেল বিটস্ট্রিং স্পেশাল ফর্ম <<>> দিয়ে ডিফাইন করা হয়। একটি বাইনারি লিটারেল ডিফাইন করার সময় আমরা ইন্টিজার ও স্ট্রিং লিটারেল ব্যবহার করতে পারি। 255-এর চেয়ে বড় ইন্টিজার মান ওভারফ্লো হবে এবং ইন্টিজারটির শুধু শেষ ৮টি বিট ব্যবহৃত হবে। ডিফল্টভাবে মানটির ওপর ::binary মডিফায়ার প্রয়োগ হয়। আমরা <>/2 অপারেটরের সাহায্যে বাইনারি কনক্যাটেনেট করতে পারি।
<<255>> == <<0xFF>>
# Overflowing bits are truncated
<<256>> == <<0>>
<<2, 4, 6, 8, 10, 12, 14, 16>> == <<0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10>>
একটি নাল-বাইট হলো <<0>>-এর আরেক নাম।
প্যাটার্ন ম্যাচিং এমনকি বাইনারিতেও সম্প্রসারিত হয়েছে, এবং একটি লিস্টের মতোই আমরা বাইনারি ডেটার একটি অংশে প্যাটার্ন ম্যাচ করতে পারি।
# Ignore the first 8 bytes, match and bind the remaining to `body`
<<_::binary-size(8), body::binary>>
অন্য ধরনের প্যাটার্ন ম্যাচিংয়ের মতোই, একাধিক ফাংশন ক্লজ থেকে বেছে নেওয়ার সময় মেলানোর জন্য আমরা এটি ফাংশন সিগনেচারে ব্যবহার করতে পারি।
আপনি একটি প্রজেক্টে কাজ করছেন, যেটি ব্যবহারকারীদের অন্য ব্যবহারকারীদের সাথে শেয়ার করার জন্য সার্ভারে ফাইল আপলোড করার সুযোগ দেয়। একটি আপলোড তার মিডিয়া টাইপ-এর সাথে মেলে কি না, তা যাচাই করার জন্য একটি ফাংশন লেখার দায়িত্ব আপনাকে দেওয়া হয়েছে। আপনি একটু খোঁজ নিয়ে জানতে পারেন যে একটি ফাইলের প্রথম কয়েকটি বাইট সাধারণত ওই ফাইল টাইপের জন্যই অনন্য, যা এটিকে এক ধরনের সিগনেচার দেয়।
রেফারেন্সের জন্য নিচের টেবিলটি দেখুন:
| ফাইল টাইপ | কমন এক্সটেনশন | মিডিয়া টাইপ | বাইনারি 'সিগনেচার' |
|---|---|---|---|
| ELF | "exe" |
"application/octet-stream" |
0x7F, 0x45, 0x4C, 0x46 |
| BMP | "bmp" |
"image/bmp" |
0x42, 0x4D |
| PNG | "png" |
"image/png" |
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A |
| JPG | "jpg" |
"image/jpg" |
0xFF, 0xD8, 0xFF |
| GIF | "gif" |
"image/gif" |
0x47, 0x49, 0x46 |
type_from_extension/1 ফাংশনটি ইমপ্লিমেন্ট করুন। এটি একটি ফাইল এক্সটেনশন (স্ট্রিং) নেবে এবং মিডিয়া টাইপ (স্ট্রিং) রিটার্ন করবে, অথবা এক্সটেনশনটি প্রত্যাশিতগুলোর সাথে না মিললে nil রিটার্ন করবে।
FileSniffer.type_from_extension("exe")
# => "application/octet-stream"
FileSniffer.type_from_extension("txt")
# => nil
type_from_binary/1 ফাংশনটি ইমপ্লিমেন্ট করুন। এটি একটি ফাইল (বাইনারি) নেবে এবং মিডিয়া টাইপ (স্ট্রিং) রিটার্ন করবে, অথবা ফাইলের সিগনেচার প্রত্যাশিতগুলোর সাথে না মিললে nil রিটার্ন করবে।
file = File.read!("application.exe")
FileSniffer.type_from_binary(file)
# => "application/octet-stream"
file = File.read!("example.txt")
FileSniffer.type_from_binary(file)
# => nil
ফাইলটিকে বাইনারি হিসেবে পড়া নিয়ে চিন্তা করবেন না। ধরে নিন যে সেটি আপনার জন্য করা হয়েছে এবং টেস্টগুলো এটি একটি আর্গুমেন্ট হিসেবে দিয়েছে।
verify/2 ফাংশনটি ইমপ্লিমেন্ট করুন। এটি একটি ফাইল (বাইনারি) এবং একটি এক্সটেনশন (স্ট্রিং) নেবে এবং একটি :ok অথবা :error টাপল রিটার্ন করবে।
file = File.read!("application.exe")
FileSniffer.verify(file, "exe")
# => {:ok, "application/octet-stream"}
FileSniffer.verify(file, "png")
# => {:error, "Warning, file format and file extension do not match."}
Exercism-এ সাইন আপ করুন, Elixir ট্র্যাকের 58টি কনসেপ্ট168টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।